题目要求:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)思路:这个问题可以退化成先找一个数a, 然后在剩下的集合中找两个数使它们的和为 target - a; 所以先将数组排序,然后顺次遍历, 使当前数位选中的数,再在剩余的集合中找到符合要求的两个数。
代码:
vector<vector<int> > threeSum(vector<int> &num) { sort(num.begin(), num.end()); // return DFS(num, 0, 3, 0); ans.clear(); if(num.size() < 3) return ans; int count = num.size() - 2; vector<int> triple(3, 0); int current = num[0]; triple[0] = num[0]; //每次挑出一个数 for(size_t i = 0; i < count; ++i) { if(i && num[i] == current) continue; triple[0] = num[i]; int j = i + 1; int k = num.size() - 1; while(j < k) { int sum = triple[0] + num[j] + num[k]; if(sum == 0) { triple[1] = num[j]; triple[2] = num[k]; //因为都是按顺序找的所以出现重复也肯定是相邻的 if(ans.size() == 0 || triple != ans[ans.size() - 1]) ans.push_back(triple); ++j; --k; } else if(sum > 0) --k; else ++j; } current = num[i]; } return ans; }
题目要求:
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).思路与3 sum差不多,就是在找的过程中记录更新最小值。最后返回:
代码:
int threeSumClosest(vector<int> &num, int target) { if(num.size() < 3) return abs(target); sort(num.begin(), num.end()); int min_dist = numeric_limits<int>::max(); int res; for(size_t i = 0; i < num.size(); ++i) { int j = i + 1, k = num.size() - 1; int sum = 0; while(j < k) { sum = num[i] + num[j] + num[k]; if(sum == target) return sum; else if(sum > target) --k; else ++j; if(min_dist > abs(sum - target)) { min_dist = abs(sum - target); res = sum; } } } return res; }
4-sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)思路: 与3-sum的做法差不多, 只是这次要先选两个数,然后再在剩下的数组中找到符合要求的另外两个数, 其实最后一步步退化成2-sum
代码:
vector<vector<int> > fourSum(vector<int> &num, int target) { vector<vector<int> > ret; set<vector<int> > unique_res; if(num.size() < 4) return ret; sort(num.begin(), num.end()); vector<int> tmp_four(4, 0); for(size_t i = 0; i < num.size(); ++i) { for(size_t j = i + 1; j < num.size(); ++j) { tmp_four[0] = num[i], tmp_four[1] = num[j]; int begin = j + 1, end = num.size() - 1; while(begin < end) { int sum = tmp_four[0] + tmp_four[1] + num[begin] + num[end]; if(sum == target) { tmp_four[2] = num[begin]; tmp_four[3] = num[end]; unique_res.insert(tmp_four); --end; ++begin; } else if(sum > target) --end; else ++begin; } } } for(set<vector<int> >::iterator iter = unique_res.begin(); iter != unique_res.end(); ++iter) ret.push_back(*iter); return ret; }
思路与3-sum和4-sum,一步步退化成找2-sum
代码:
vector<vector<int> > DFS(vector<int>& num, int begin, int count, int sum) { // const int len = num.size(); set<int> visited; vector<vector<int> > ret; vector<int> triple; if(count == 2) { int i = begin, j = num.size() - 1; while(i < j) { if((num[i] + num[j]) == sum) { triple.clear(); triple.push_back(num[i]); triple.push_back(num[j]); ret.push_back(triple); ++i; --j; } else if((num[i] + num[j]) > sum) --j; else ++i; } } else { for(size_t i = begin; i < num.size(); ++i) { if(visited.count(num[i]) == 0) { visited.insert(num[i]); vector<vector<int> > subset = DFS(num, i + 1, count - 1, sum - num[i]); if(!subset.empty()) { for(size_t j = 0; j < subset.size(); ++j) subset[j].insert(subset[j].begin(), num[i]); ret.insert(ret.end(), subset.begin(), subset.end()); } } } } return ret; }