Valid Triangle Number
Input: [2,2,3,4]
Output: 3
Explanation:
Valid combinations are:
2,3,4 (using the first 2)
2,3,4 (using the second 2)
2,2,3Input: [2,2,3,4]
Output: 3
Explanation:
Valid combinations are:
2,3,4 (using the first 2)
2,3,4 (using the second 2)
2,2,3 # 解法1,排序,对于每个a,b,用二分法确定c的最大值(excluded)
class Solution(object):
def triangleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# binary search to find the index of last element that less than target
def biSearch(start, target):
if start >= len(nums): return -1
p = start
r = len(nums) - 1
while p + 1 < r:
q = p + (r - p) / 2
if nums[q] >= target:
r = q
else:
p = q
if nums[r] < target: return r
if nums[p] < target: return p
else: return -1
# Main part
nums.sort()
ret = 0
# 对每一对a,b,找最大的c,则 b 到 最大c 之间的值都可以作为第三边
for i in range(len(nums) - 1):
for j in range(i + 1, len(nums)):
if nums[i] == 0 or nums[j] == 0: continue
target = nums[i] + nums[j]
idx_c = biSearch(j + 1, target)
if idx_c < 0: continue
ret += idx_c - j
return ret if ret > 0 else 0 # 解法2, 双指针遍历,每次固定第三条边,找a,b的范围
class Solution:
"""
@param: S: A list of integers
@return: An integer
"""
def triangleNumber(self, S):
# 两个短边的和大于第三边就可以组成三角形
# 所以可以排序后,从右向左选择边长作为第三边,用双指针确定另外两边组合数量
# 三边分别为 a,b,c, 时间复杂度为O(n^2)
if not S or len(S) < 3:
return 0
S.sort()
res = 0
for c in range(len(S) - 1, 1, -1):
## 接下来转变为求a,b的和大于c的组合个数的问题
## 每次固定b,找a的最小值,然后res加上b-a
a, b = 0, c - 1
while a < b:
if S[a] + S[b] > S[c]:
res += b - a
b -= 1
else:
a += 1
return res // brute force then check
public class Solution {
private int count = 0;
public int triangleNumber(int[] nums) {
dfs(nums, 0, 3, new ArrayList<Integer>());
return count;
}
private void dfs(int[] nums, int pos, int remainLength, List<Integer> path) {
if (remainLength == 0) {
if (isValid(path)) count++;
return;
}
if (remainLength > 0 && pos >= nums.length) return;
for (int i = pos; i < nums.length; ++i) {
path.add(nums[i]);
dfs(nums, i + 1, remainLength - 1, path);
path.remove(path.size() - 1);
}
}
private boolean isValid(List<Integer> edges) {
int a = edges.get(0);
int b = edges.get(1);
int c = edges.get(2);
if (a + b <= c || a + c <= b || c + b <= a) return false;
return true;
}
} // two pointers
public class Solution {
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
int ret = 0;
for (int c = nums.length - 1; c >= 2; --c) {
int a = 0;
int b = c - 1;
while (a < b) {
if (nums[a] + nums[b] > nums[c]) {
ret += b - a;
b--;
} else {
a++;
}
}
}
return ret;
}
} class Solution {
// 二分法, 对于每一对a,b,找比他们大的符合条件的最大边长c,
// 则c到b之间的值(包括c)都可以作为第三条边
public int triangleNumber(int[] nums) {
if (nums.length < 3) return 0;
Arrays.sort(nums);
int ret = 0;
for (int a = 0; a < nums.length - 2; ++a) {
for (int b = a + 1; b < nums.length - 1; ++b) {
int c = biSearch(nums, b + 1, nums[a] + nums[b]);
if (c == -1) continue;
ret += c - b;
}
}
return ret;
}
// 找到start(include)之后小于target的最大的数的index
private int biSearch(int[] nums, int start, int target) {
int p = start, r = nums.length - 1;
while (p + 1 < r) {
int q = p + (r - p) / 2;
if (nums[q] < target) p = q;
else r = q;
}
if (nums[r] < target) return r;
else if (nums[p] < target) return p;
else return -1;
}
}