这道题的思路是排序+双指针。
对于排好序的数组,存在以下几种情况:
- 当元素
i
为正数时,其之后的数字不在存在三数之和等于0的情况了。 - 当元素
i
为负数或0时,为了避免重复,依次从头遍历数组,检查当前元素i之后的区间里,是否存在nums[i] + nums[L] + nums[R]
的情况,其中L
从i+1
开始向右遍历,R
从n-1
开始向左遍历。 - 其中,若
nums[i] + nums[L] + nums[R] == 0
,则保存答案,遍历L
和R
继续找包含元素i
的三数之和,若小于0,则表示左边界过小,L++
,若大于0,则表示右边界过大,R--
。 - 在遍历
i
、L
和R
的时候,要注意避开重复数字。 - 考虑边界情况:当
nums.size()
小于3时,直接返回空数组{}
。
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> ans;sort(nums.begin(), nums.end());int n = nums.size();if (n < 3) return {};for (int i = 0; i < n; ++i) {if (nums[i] > 0) break;if (i > 0 && nums[i] == nums[i - 1]) continue;int L = i + 1, R = n - 1;while (L < R) {if (nums[i] + nums[L] + nums[R] == 0) {ans.push_back({nums[i], nums[L], nums[R]});while (L < R && nums[L] == nums[L + 1]) ++L;while (L < R && nums[R] == nums[R - 1]) --R;++L;--R;} else if (nums[i] + nums[L] + nums[R] < 0) {++L;} else {--R;}}}return ans;}
};
链接以前同一道题的博客记录