双指针算法进阶
双指针是处理有序数组问题的利器,尤其在涉及两数之和、三数之和等经典场景时,能显著降低时间复杂度。本文将通过四个典型例题,梳理双指针在不同场景下的应用逻辑与细节处理。
有效三角形个数
题目背景
给定一个包含非负整数的数组,统计其中能构成三角形的三元组个数。
核心思路
构成三角形的条件是任意两边之和大于第三边。若将三边排序为 a ≤ b ≤ c,则只需满足 a + b > c 即可。
利用这一性质,我们可以先对数组升序排序。固定最长边(即第三边),然后使用双指针在剩余元素中寻找满足条件的另外两边。具体策略如下:
- 排序:将数组按升序排列。
- 固定最大边:从右向左遍历,将当前元素视为最长边
nums[i]。 - 双指针查找:左指针
left指向起始位置,右指针right指向i-1。- 若
nums[left] + nums[right] > nums[i],说明left到right-1之间的所有元素与nums[right]组合均满足条件(因为数组已排序),此时累加right - left个解,并将right左移继续尝试。 - 若和小于等于第三边,则需增大较短边,移动
left指针。
- 若
- 终止条件:当
left >= right时结束内层循环。
注意:由于需要三个边,最长边的索引至少为 2,因此外层循环从
size() - 1开始,直到2。
代码实现
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;
(left < right) {
(nums[left] + nums[right] > nums[i]) {
count += right - left;
right--;
} {
left++;
}
}
}
count;
}
};


