题目
思路
难点在于不允许出现重复的三元组,所以不能单纯使用三重循环求解。
-
在三重循环的基础上考虑,我们可以在三元组中指定某种顺序,例如:保证{a,b,c} 满足a<=b<=c。只访问并保存该顺序的三元组,即可规避重复问题,这时需要对原数组进行排序。
-
解决排序问题后,还要注意可能出现重复元素,也会导致三元组重复,所以移动指针时需要跳过重复元素。
-
在原来三重循环+排序的基础上可以发现,如果向右移动b,b的值会变大,此时c只能减小才可能满足条件,所以c只能在原来的左侧寻找,因此可以把二、三重循环合并,采用双指针指向b、c,b、c的移动同时进行,并维持b索引 < c索引。
C+代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
vector<vector<int>>ret;
sort(nums.begin(), nums.end()); //排序
for (int i = 0; i < n - 2; i++) { //abc的索引:i j k
if (i > 0 && nums[i] == nums[i - 1])continue; //跳过重复元素
int k = n - 1;//第三个数的索引,开始指向末尾
for (int j = i + 1; j < n - 1; j++) {
if (j > i + 1 && nums[j] == nums[j - 1])continue;//跳过重复元素
while (j < k&&nums[i] + nums[j] + nums[k]>0) k--; //k索引左移
if (j == k)break;//若指针相遇,j再怎么增加也不会有满足条件的j k
if (nums[i] + nums[j] + nums[k] == 0)
ret.push_back({ nums[i] , nums[j] , nums[k] });
}
}
return ret;
}
};