Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c= 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
方法一:
二分法,先排序,注意剪枝,前后各一个指示,中间的靠二分法搜索。速度比较慢,但空间复杂度高于90%
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int sz = nums.size();
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int i = 0; i < sz - 2; i++) {
if (i > 0 && nums[i - 1] >= 0) //{0,0,0,0}
break;
while (i > 0 && nums[i] == nums[i - 1])
i++;
for (int k = sz - 1; k > i + 1; k--) {
while (k > i + 2 && nums[k] == nums[k - 2]) {
k--;
}
if (nums[i] + 2 * nums[k] < 0) //剪枝{-4,*,1}
break;
if (nums[i] * 2 + nums[k] > 0) //剪枝{-2,*,5}
continue;
int l = i, r = k;
while (l < r) {
int j = (l + r) / 2;
if (j == l || j == r)
break;
int tmp = nums[i] + nums[j] + nums[k];
if (tmp == 0) {
res.push_back({ nums[i] , nums[j] , nums[k] });
if (nums[k] == nums[k - 1])
k--;
break;
}
else if (tmp > 0)
r = j;
else
l = j;
}
}
}
return res;
}
};
方法二:
同样先排序,同样剪枝,用j记录使得三数和最接近0的数的中间位置,时间快于86%的人,空间高于93%
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int sz = nums.size();
vector<vector<int>> res;
sort(nums.begin(), nums.end());
int j = (sz - 1) / 2;
for (int i = 0; i < sz - 2; i++) {
if (i > 0 && nums[i - 1] >= 0) //{0,0,0,0}
break;
while (i > 0 && nums[i] == nums[i - 1])
i++;
for (int k = sz - 1; k > i + 1; k--) {
while (k > i + 2 && nums[k] == nums[k - 2]) {
k--;
}
if (nums[i] + 2 * nums[k] < 0) //{-5,*,2}
break;
if (nums[i] * 2 + nums[k] > 0) //{-2,*,5}
continue;
if (j <= i) //确保j在i和k之间
j = i + 1;
else if (j >= k)
j = k - 1;
int tmp = nums[i] + nums[k];
if (tmp + nums[j] == 0) {
res.push_back({ nums[i] , nums[j] , nums[k] });
}
else if (tmp + nums[j] > 0) {
while (nums[j - 1] > -tmp)
j--;
if (nums[j - 1] == -tmp && j - 1 > i) {
res.push_back({ nums[i] , nums[j - 1] , nums[k] });
}
}
else {
while (nums[j + 1] < -tmp)
j++;
if (nums[j + 1] == -tmp && j + 1 < k) {
res.push_back({ nums[i] , nums[j + 1] , nums[k] });
}
}
if (nums[k] == nums[k - 1])
k--;
}
}
return res;
}
};