这道题一开始看只想到了从左往右遍历,然后再分别定义左右指针指向遍历到的元素右边的区间的首元素和尾元素,然后再不断移动左右指针来收集元素,这样的想法最大的问题在于无法处理重复元素的问题,外层的遍历循环无法去重,所有指针移动的过程中也不能去重,所以直接按照这个想法来是行不通的,我在刷代码随想录的时候也刷过这道题,看了下当时自己写的博客,马上就懂了。首先需要对输入的数组进行升序排列,然后再按照上面的想法来做,还有一点需要注意的是,当收获结果的时候,此时左右指针和外层指针i都指向了符合要求的三个元素,当i不动,左右指针继续向中间移动,仍然有可能收获新的结果,所以在左右指针相遇之前,内层循环要一直进行下去。言归正传,当收获结果后,左右指针必须向中间移动,直到左右指针指向的值都和收获结果时他们各自指向的值不同才停止。
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> result;sort(nums.begin(), nums.end()); //将数组先进行升序排序for(int i = 0; i < nums.size(); i++){if(nums[i] > 0) //后面的元素一定都大于0,没必要继续遍历了return result;if(i > 0 && nums[i] == nums[i - 1]) //去重continue;for(int left = i + 1, right = nums.size() - 1; left < right; ){if(nums[left] + nums[right] + nums[i] < 0) //三数之和小于0,需移动左指针left++;else if(nums[left] + nums[right] + nums[i] > 0) //三数之和大于0,需移动右指针right--;else{result.emplace_back(vector<int> {nums[i], nums[left], nums[right]});//注意,收集完结果之后还需要移动左右指针,左右指针也需要去重while(left < right){if(nums[left] == result.back()[1])left++;if(nums[right] == result.back()[2])right--;if(nums[left] != result.back()[1] && nums[right] != result.back()[2])break;}}}}return result;}
};
看了下灵神的代码,我的和他的思路大差不差,这里就不写了。