核心内容是关于计算数组中能构成三角形的三元组个数的算法笔记。以下从题目分析、算法分析和代码编写三个方面进行总结。
题目分析
-
问题 :给定一个非负整数数组
nums,返回其中可以构成三角形的三元组个数。 -
三角形判定定理 :对于三条边长
a,b,c(满足a ≤ b ≤ c),能构成三角形的充要条件 是a + b > c。 -
目标 :统计数组中所有满足该条件的三元组
(nums[i], nums[j], nums[k])的个数。 -
示例 :笔记中以数组
[2,2,3,4]为例进行推演。
算法分析
笔记中对比了两种主要思路:
-
暴力枚举法:
-
思路 :使用三层循环枚举所有可能的三元组
(i, j, k),并检查是否满足a + b > c。 -
缺点:时间复杂度为 O(n³),效率极低。
-
-
排序 + 双指针法(最优解):
-
思路 :利用判定定理的单调性。先对数组进行排序 ,保证后续操作中
a ≤ b ≤ c。 -
核心策略 :固定最大边
c(即nums[k]),在其左侧的子数组[0, k-1]中使用双指针寻找满足a + b > c的(a, b)对。-
初始化
left = 0,right = k-1。 -
若
nums[left] + nums[right] > nums[k]:-
由于数组有序,对于当前的
left,所有(left, left+1, ..., right)作为b都满足条件。因此,可直接将right - left个三元组加入答案。 -
然后
right--,尝试更小的b。
-
-
若
nums[left] + nums[right] ≤ nums[k]:- 说明
a太小,需要增大,执行left++。
- 说明
-
-
步骤:
-
排序数组。
-
从后向前遍历,固定最大数
nums[i]作为c。 -
在
i左侧的区间内,使用上述双指针法统计满足条件的二元组个数,并累加到答案中。
-
-
优点:时间复杂度 O(n²),远优于暴力法。
-
代码编写
以下是基于排序和双指针算法的 Java 代码实现,修正并梳理了笔记中的逻辑:
import java.util.Arrays;
class Solution {
public int triangleNumber(int[] nums) {
if (nums == null || nums.length < 3) {
return 0;
}
// 1. 排序
Arrays.sort(nums);
int count = 0;
int n = nums.length;
// 2. 固定最大的边 c (nums[i])
for (int i = n - 1; i >= 2; i--) {
int left = 0;
int right = i - 1;
// 3. 在 c 左侧的区间内使用双指针寻找 a+b > c
while (left < right) {
if (nums[left] + nums[right] > nums[i]) {
// 固定right作为b,left到right-1的所有a都满足条件
count += (right - left);
right--; // 尝试更小的 b
} else {
// a+b <= c,需要增大 a
left++;
}
}
}
return count;
}
}
代码说明:
-
Arrays.sort(nums):排序是后续双指针算法正确性的基础。 -
外层循环
for (int i = n - 1; i >= 2; i--):从大到小依次固定最长边c。 -
内层
while循环:标准的双指针搜索,核心在于当nums[left] + nums[right] > nums[i]成立时,可以利用有序性一次性计算出多组解,这是提升效率的关键。 -
最终返回累加得到的
count。