题目
C++ solution
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
if (nums.size() <= 2 || nums.back() < 0 || nums.front() > 0)
{
return {};
}
for (int i = 0; i < nums.size() - 2, nums[i] <= 0; ++i) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int tar = 0 - nums[i];
for (int j = i + 1, k = nums.size() - 1; j < k; ) {
if (nums[j] + nums[k] == tar) {
result.push_back({nums[i], nums[j], nums[k]});
while (j < k && nums[j] == nums[j + 1]) ++j;
while (j < k && nums[k] == nums[k - 1]) --k;
++j; --k;
} else if (nums[j] + nums[k] < tar) ++j;
else --k;
}
}
return result;
}
};
简要题解
- 首先对原数组进行排序;
- 若数组长度小于3或有序数组的第一个数大于0或最后一个数小于0,则没有和为0的三个数;
- 然后开始遍历排序后的数组。当遍历到倒数第二个数或遇到正数时就结束循环,因为有序数组一个正数后面的数字都是正数,就永远不会出现和为0的情况了。
- 由于题目要求找出不同的数组,处理方法是从第二个数开始,如果和前面的数字相等,就跳过。
- 对于遍历到的数,用0减去这个数得到一个 target,用两个下标分别指向该数字之后的数组首尾两个数,如果两个数之和正好为 target,则将这三个数一起存入结果中,然后跳过重复数字;如果两个数之和小于 target,则将左边的下标递增,使得指向的数字增大一些;同理,如果两个数之和大于 target,则将右边的下标递减,使得指向的数字减小一些。