LeetCode 611. 有效三角形的个数
题目描述
思路分析
解法一:排序 + 双指针(推荐)
核心思路:
- 三角形成立的条件是任意两边之和大于第三边。对于排序后的数组,只需验证最小两边之和 > 最大边。
- 先对数组升序排序,然后从最大边
k开始向左枚举,用双指针i(左)和j(右,初始为k-1)在[0, k-1]范围内寻找满足nums[i] + nums[j] > nums[k]的对数。- 当
nums[i] + nums[j] > nums[k]时,由于数组有序,[i, j-1]范围内的所有左指针与j组合均满足条件,共j - i对,将结果加上j - i后将j左移。- 当
nums[i] + nums[j] <= nums[k]时,说明左指针太小,将i右移增大。
复杂度分析:
- 时间复杂度:O(n²),其中 n 表示数组长度,排序 O(n log n),双重循环 O(n²) 主导
- 空间复杂度:O(log n),其中 log n 为排序使用的递归栈空间
class Solution {
public int triangleNumber(int[] nums) {
// 升序排序,使得对于固定最大边,只需验证最小两边之和 > 最大边
Arrays.sort(nums);
int res = 0;
int n = nums.length;
// 枚举最大边 k,从右向左遍历
for (int k = n - 1; k >= 2; k--) {
int i = 0, j = k - 1;
// 双指针在 [0, k-1] 范围内寻找满足条件的对数
while (i < j) {
if (nums[i] + nums[j] > nums[k]) {
// [i, j-1] 与 j 的组合均满足条件,共 j - i 对
res += j - i;
j--;
} else {
// 两数之和不足,左指针右移增大
i++;
}
}
}
return res;
}
}
func triangleNumber(nums []int) int {
// 升序排序,使得对于固定最大边,只需验证最小两边之和 > 最大边
sort.Ints(nums)
res := 0
n := len(nums)
// 枚举最大边 k,从右向左遍历
for k := n - 1; k >= 2; k-- {
i, j := 0, k-1
// 双指针在 [0, k-1] 范围内寻找满足条件的对数
for i < j {
if nums[i]+nums[j] > nums[k] {
// [i, j-1] 与 j 的组合均满足条件,共 j - i 对
res += j - i
j--
} else {
// 两数之和不足,左指针右移增大
i++
}
}
}
return res
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 15. 三数之和 | 中等 | 排序 + 双指针、枚举固定值 |
| 16. 最接近的三数之和 | 中等 | 排序 + 双指针、最优值更新 |
| 18. 四数之和 | 中等 | 排序 + 双指针、多层枚举 |
| 259. 较小的三数之和 | 中等 | 排序 + 双指针、计数 |
| 1099. 小于 K 的两数之和 | 简单 | 排序 + 双指针 |
| 167. 两数之和 II - 输入有序数组 | 中等 | 双指针 |
| 11. 盛最多水的容器 | 中等 | 双指针、贪心 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!
