双指针算法进阶实战
双指针是处理数组相关问题的利器,配合排序往往能大幅降低时间复杂度。本文将通过四个经典案例,从基础的两数之和扩展到三数、四数之和以及三角形计数,梳理其中的核心逻辑与去重技巧。
1. 有效三角形个数
题目描述
给定一个包含非负整数的数组,找出其中能组成三角形的三元组个数。
核心思路
构成三角形的条件是任意两边之和大于第三边。若将三边排序为 a ≤ b < c,只需满足 a + b > c 即可。
为了高效判断,我们先将数组升序排序。固定最大边 nums[i],问题转化为在 [0, i-1] 区间内寻找两个数 left 和 right,使得 nums[left] + nums[right] > nums[i]。
利用单调性:
- 若
nums[left] + nums[right] > nums[i],说明对于当前right,所有k ∈ [left, right-1]均满足条件(因为nums[k] ≥ nums[left]),此时可一次性累加right - left个解,然后right--继续尝试更小的右边。 - 若
nums[left] + nums[right] <= nums[i],说明左边太小,需left++增大和。
代码实现
class Solution {
public:
int triangleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end()); // 升序排序
int count = 0;
// 从右往左依次将最大值作为第三边
for (int i = nums.size() - 1; i >= 2; i--) {
int left = 0;
int right = i - 1;
while (left < right) {
if (nums[left] + nums[right] > nums[i]) {
count += right - left; // 中间所有元素均满足
right--;
} {
left++;
}
}
}
count;
}
};


