题目
问题分析
在这一题一开始直接使用的是深搜,但是最后20例数据超时,采取剪枝后仍然有三组数据过不过去。(在去重部分,采用的是book数组进行记录,将相同数据进行统一记载,内层再一个min(3,book[i])~1的循环)。
然后,看题解,这题的正确过法就是双指针了。采取固定第一位,查找第二位和第三位,指针的左右移动要去重,当然,固定的第一位也要去重。
去重方法:
引用自Krahets
编码
Python题解
这里是深搜+剪枝
class Solution:
def threeSum(self, nums):
nums.sort()
self.book = dict()
for i in nums:
if i in self.book.keys():
self.book[i] += 1
else:
self.book[i] = 1
self.max2 = nums[-1]+nums[-2]
self.max1 = nums[-1]
self.nums = list(self.book.keys())
self.book = list(self.book.values())
self.ans = []
self.dfs(0, [], 0, 2)
return self.ans
def dfs(self, start: int, num, tsum: int, n):
if (n == -1):
self.ans.append(num)
else:
for i in range(start, len(self.book)):
for m in range(1, min(self.book[i]+1,4))[::-1]:
self.book[i] -= m
ts = tsum + self.nums[i] * m
if ts > 0:
return
if (n - m == 1 and ts + self.max2 < 0) or (n - m == 0 and ts + self.max1 < 0) or (n - m == -1 and ts != 0):
self.book[i] += m
break
self.dfs(i+1, num + [self.nums[i]]*m, ts, n - m)
ts -= self.nums[i] * m
self.book[i] += m
运行结果
C++题解
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if(nums.size() < 3){
return res;
}
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); ++i){
if(i == 0 || nums[i] != nums[i-1]){ // 去重
findTarget(i+1, res, nums, -1 * nums[i]);
}
}
return res;
}
void findTarget(int l, vector<vector<int>> &ans, vector<int>& nums, int target){
int r = nums.size() - 1, start = l, end = nums.size() - 1;
vector<int> sum_zero;
while(l < r){
if(nums[l] + nums[r] == target){
if(l == start || r == end){ // 保证有左右值
vector<int> sum_zero({-target, nums[l], nums[r]});
ans.push_back(sum_zero);
++l;
--r;
}else if(nums[l] == nums[l-1] || nums[r] == nums[r+1]){ // 去重(保证之前没有被记录过)
++l;
--r;
}else{
vector<int> sum_zero({-target, nums[l], nums[r]});
ans.push_back(sum_zero);
++l;
--r;
}
}else if(nums[l] + nums[r] > target){
--r;
}else{
++l;
}
}
}
};
运行结果
容器使用总结
vector<vector<int>> res
nums.size()
sort(nums.begin(), nums.end());
vector<int> sum_zero({-target, nums[l], nums[r]});
ans.push_back(sum_zero);
补充题
最邻近的三数之和
class Solution {
public:
int threeSumClosest(vector<int>& nums , int target) {
int ans = 9999;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); ++i){
if(i == 0 || nums[i] != nums[i-1]){ // 去重
findTarget(i+1, ans, nums, target - nums[i]);
}
}
return target - ans;
}
void findTarget(int l, int &ans, vector<int>& nums, int target){
int r = nums.size() - 1, start = l, end = nums.size() - 1;
while(l < r){
int tempsub = target - nums[l] - nums[r];
if(fabs(tempsub) < fabs(ans)){
ans = tempsub;
}
if(tempsub > 0){
++l;
}else{
--r;
}
}
}
};