上一题的加强版,主要思路类似,建议与上一题同时食用。。。这题题目的变化是,数组不再有序,同时有了重复的数字出现,但不允许多次取同一个值,这就稍微有点麻烦。二话不说先排序,方便后续操作。
这里需要满足的要求有两个:首先,每一次迭代,在遍历候选元素的时候,同一位置的元素如果上一次迭代已经选过,这次不能选。其次,每一次迭代,相同元素,只能选择一个继续迭代,否则会有重复结果产生,例如数组中有连续3个2出现,你只能选择一个2迭代,然后继续遍历2后边的元素。
想清楚这一点就好办了,为了解决上述第一个要求,我们用一个bool数组,来记录每个位置是否被访问,如果被访问过,则这次迭代不再选择。为了解决第二个要求,我们在一次选择和处理后,用一句:while(i + 1 < candidates.size() && candidates[i + 1] == candidates[i])i++;(这是上次有道题目里,答案用了这个方式来跳过数组中后续的相同元素,忘了是哪道),这样就达到了不重复迭代的要求。
class Solution {
public:
vector<vector<int> > results;
vector<vector<int> > combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
results.clear();
vector<int> cur;
bool visit[candidates.size()] = {0};
backtracking(candidates, target, cur, visit);
return results;
}
void backtracking(vector<int>& candidates, int target, vector<int>& cur, bool * visit)
{
int prePick = cur.empty()? 0: cur[cur.size() - 1];
for(int i = 0; i < candidates.size(); i++){
if(candidates[i] >= prePick && candidates[i] <= target){
if(!visit[i]){
visit[i] = 1;
cur.push_back(candidates[i]);
if(candidates[i] == target) results.push_back(cur);
else backtracking(candidates, target - candidates[i], cur, visit);
cur.pop_back();
visit[i] = 0;
while(i + 1 < candidates.size() && candidates[i + 1] == candidates[i])i++;
}
}
}
}
};