[LeetCode 15.] 三数之和
LeetCode 15. 三数之和
题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
- 0 <= nums.length <= 3000
- -105 <= nums[i] <= 105
解题思路
经典双指针问题。
也可以用哈希,注意去重和三元组中重复元素的问题。哈希更慢,因为有元素重复问题需要处理,还有额外空间开销。
参考代码
双指针
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
if (nums.size() < 3) return {};
sort(nums.begin(), nums.end()); // for unique result
if (nums[0] > 0) return {};
vector<vector<int>> res;
size_t n = nums.size();
for (size_t i =0; i<n; i++) {
if (i > 0 && nums[i-1] == nums[i]) continue; // 去重
size_t j = i+1;
size_t k = n-1;
while (j < k) {
if (nums[i] + nums[j] + nums[k] < 0) {
j++;
} else if (nums[i] + nums[j] + nums[k] > 0) {
k--;
} else {
if (!(j > i+1 && nums[j-1] == nums[j]
&& k < n-1 && nums[k] == nums[k+1])) { // 去重
// 有序 nums[i] <= nums[j] <= nums[k]
res.push_back({nums[i], nums[j], nums[k]});
}
j++;
k--;
}
}
}
return res;
}
};
排序+哈希
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
if (nums.size() < 3) return {};
sort(nums.begin(), nums.end()); // for unique result
if (nums[0] > 0) return {};
unordered_map<int,int> cnt;// <num, cnt>
for (int x : nums) {
cnt[x]++;
}
vector<vector<int>> res;
size_t n = nums.size();
for (size_t i =0; i<n; i++) {
if (i > 0 && nums[i-1] == nums[i]) continue; // 去重
for (size_t j=i+1; j<n; j++) {
if (j > i+1 && nums[j-1] == nums[j]) continue; // 去重
int x = nums[i] + nums[j];
// if (cnt[-x] && nums[j] <= -x) { // 有序
if (nums[j] > -x) continue;
if ((cnt[-x] >= 1 && nums[j] < -x)
|| (cnt[-x] >= 2 && nums[i] < nums[j] && nums[j] <= -x)
|| (cnt[-x] >= 3 && nums[i] == -x)) { // 有序
res.push_back({nums[i], nums[j], -x});
}
}
}
return res;
}
};