从给定的数组中找到4个数的组合,和==target。组合不能重复,按非递减顺序。
大致思路:
要或不要,dfs。但是AC代码(别人的题解)里的剪枝很棒,结合了“按非递减顺序——递增顺序”的题意。
另外,对于重复的问题,使用的是set来对vector<int>型的变量去重(比去find那种要快,而且不需要对结果重新排序)
AC代码:
class Solution {
int N = 4;
public:
// 使用DFS的思想来完成
vector<vector<int> > fourSum(vector<int> &num, int target=0) {
vector<vector<int>> result;
set<vector<int>> res;
vector<int> vi;
sort(num.begin(), num.end());
dfs(res, vi, num, target, 0, 0);
// sort(result.begin(), result.end());
// result.erase(unique(result.begin(),result.end()),result.end());
for(auto a:res){
result.push_back(a); //最后把set的东西复制到结果的类型里去
}
return result;
}
void dfs(set<vector<int>> &res, vector<int> &vi, vector<int> &num, int target, int start, int cnt) {
if(cnt==N){
if(target==0){
res.insert(vi);
}
return;
}
// 选择一个开始位置
for(int i=start;i<num.size();++i){
// cnt表示已经累加的数, 加上当前数的话, 还有n-cnt-1个数
// 所需要的是target-num[i], 这个数一定要大于(N-cnt-1)*num[i])才行!!!!
if(target-num[i]<(N-cnt-1)*num[i]){
break;
}
// 选择了某条通路
vi.push_back(num[i]);
// 在该通路上继续前行
dfs(res,vi, num, target-num[i] , i+1, cnt+1);
// 恢复现场, 走完了某条通路, 需要恢复现场
vi.pop_back();
}
}
};