一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
题目描述
给定一个包含非负整数的数组 nums
,返回其中可以组成三角形三条边的三元组个数。
示例
输入: nums = [2,2,3,4]
输出: 3
解释: 有效的组合是:
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3
输入: nums = [4,2,3,4]
输出: 4
提示
1 <= nums.length <= 1000
0 <= nums[i] <= 1000
排序 + 二分查找
假设有三条边,从小到大依次为i,j,k
。如果k
的长度小于i + j
,那么,这三条边必定无法构建成一个三角形。
根据上面的结论,我们可以将数组按照从小到大进行排序,这样即可以利用二分查找来快速定位到当前组合的边界点,统计出符合条件的三元组个数。
步骤:
- 先将数组进行排序
- 遍历数组,当前指针
i
表示为三条边中最短的一条边 - 第二层遍历,当前指针
j
表示为三条边的中间值 - 二分查找,通过取中间点比较,判断当前组合是否符合三角形,每次排除剩余一半的元素
- 累加结果
class Solution {
public int triangleNumber(int[] nums) {
int max = 0, n = nums.length;
// 将数组排序
Arrays.sort(nums);
// 遍历数组,i 表示三角形中第一条边
for(int i = 0; i < n - 2; ++i){
// 遍历数组,j 表示三角形中第二条边
for(int j = i + 1; j < n - 1; ++j){
// 二分查找
int left = j + 1, right = n - 1, k = j;
while(left <= right){
// 取中间点
int mid = (right + left) >> 1;
// 判断符合条件,则指针右移,统计左边元素
if(nums[mid] < nums[i] + nums[j]){
k = mid;
left = mid + 1;
}else{
// 不符合条件,指针左移,舍弃右边的元素
right = mid - 1;
}
}
// 结果累加
max += k - j;
}
}
return max;
}
}