算法笔记
本题与之前所做过的力扣40题组合总和II问题类似,都包含了去重的相关操作,其次结合算法笔记7的子集问题(78题),本题就可以迎刃而解了。
题目描述
本题与上题的不同之处主要还是可能包含了重复元素,面对重复问题我们只需要考虑在原来子集问题的基础上加入used数组进行去重操作。
解题步骤
三部曲:
1.选择参数: 参数依然老三样,记录路径的一维数组path,记录结果的二维数组result,确定范围的参数startIndex。除此之外为了实现去重操作,依然要拿出uesd数组进行去重。
2.终止条件: 终止条件与上题一样不需要什么变化,只需要注意将result记录结果的步骤放在ig判断外以防漏掉某些节点。
3.循环递归回溯:
关于去重操作的具体步骤,在上面代码随想录的图例中已经体现的比较明显了,至于具体的去重方式如果看不懂图示,建议去优先看我的组合总和II的题解,这里就不多加赘述,只需要注意使用used数组去重不要忘了提前对于给定数组进行排序 。除了去重操作,其它的代码部分与上题几乎一样,for循环递归与回溯,至此解决问题。
代码部分
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
void backtracking(vector<int>& nums, int startIndex, vector<bool>& used) {
result.push_back(path);
if(startIndex >= nums.size()) {
return;
}
for(int i = startIndex; i < nums.size(); i++) {
if(i > 0 && nums[i - 1] == nums[i] && used[i - 1] == false) {
continue;
}
path.push_back(nums[i]);
used[i] = true;
backtracking(nums, i + 1, used);
used[i] = false;
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<bool> used(nums.size(), false);
sort(nums.begin(), nums.end());
backtracking(nums, 0, used);
return result;
}
};
结语
今天的题目同昨天相似,都是使用类似的方法解决类似的问题,一方面可以更深入了解子集问题与组合问题的异同之处,另一方面也是对之前去重方法的复习。希望可以好好消化。如果不懂子集问题可以在子集问题中寻找答案,如果不理解去重操作可以回顾一下组合总和II,相信看完两道题一定会明白本题。