- 题目
给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。
- 示例
输入: nums = [4,2,3,4]
输出: 4
- 算法
先排序
对于每一个确定的nums[i]点,从它的前面找出能组成三角形的两个点
left = 0, right = i - 1;
如果此时可以组成三角形(nums[left] + num[right] > nums[i]),则nums[left] ~num[right-1]都可以与num[right]和nums[i]组成三角形
res += right - left; right–
如果此时不行,则left++
- 代码
// 双指针
// 因为有单调性,所以可以双指针解决
// 先确定i,对于j来说,j越小,k就越大,或者不变。
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
int res = 0;
for (int i = 2; i < nums.length; i++){
int k = 0;
for (int j = i - 1; j >= 1;j--) {
// 寻找第一个可以构成三角形的边
while (k < j && nums[k] + nums[j] <= nums[i]) {
k++;
}
// 更大的j都找不到k点组成三角形,更小的j更不行,直接break
if (k == j) {
break;
}
res += j - 1 - k + 1;
}
}
return res;
}
- 算法
先枚举两条边,确定两条边后,再确定第三条边的位置。
确定两条边后,第三条边的位置是满足二分条件的。
即,前面的边不能构成三角形,后面的边能构成三角形,二分法找出第一个可以构成三角形的边,然后这条边后边的边一定也可以构成三角形。
- 代码
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
int res = 0;
for (int i = 2; i < nums.length; i++) {
for (int j = i - 1; j >= 1; j--) {
int left = 0;
int right = j - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] + nums[j] <= nums[i]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if (left != j) {
res += j - 1 - left + 1;
}
}
}
return res;
}