核心思路
在处理数组求和或判定类问题时,排序配合双指针往往能将时间复杂度从 O(n²) 优化至 O(n²) 甚至更低。其核心在于利用有序数组的单调性:固定一个元素后,通过移动左右指针来逼近目标值。
下面我们通过四个经典例题,逐步拆解这一技巧在不同场景下的应用与细节处理。
611. 有效三角形个数
问题背景
给定一个包含非负整数的数组,判断其中有多少个三元组能构成三角形。
解题逻辑
构成三角形的条件是任意两边之和大于第三边。在排序后的数组中,若选定最长边为 nums[i],只需满足 nums[left] + nums[right] > nums[i] 即可。由于数组已升序排列,一旦该条件成立,则 left 到 right-1 之间的所有元素与 nums[right] 的组合均满足条件。
具体步骤如下:
- 排序:将数组按升序排列。
- 固定最大边:从右向左遍历,将当前元素视为最长边
nums[i]。 - 双指针收缩:左指针
left指向起始位置,右指针right指向i-1。- 若
nums[left] + nums[right] > nums[i],说明left到right之间的所有元素都能与nums[right]构成三角形,数量为right - left。随后right--继续尝试更小的组合。 - 若和不满足,则
left++,增大两数之和。
- 若
- 终止条件:当
left >= right时结束内层循环。

代码实现
class Solution {
public:
int triangleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end()); // 升序排序
int count = 0;
// 从右往左依次将最大值作为第三边
for (int i = nums.size() - ; i >= ; i--) {
left = ;
right = i - ;
(left < right) {
(nums[left] + nums[right] > nums[i]) {
count += right - left;
right--;
} {
left++;
}
}
}
count;
}
};


