题意:
给定一个整数数组 nums ,其中可能包含重复元素,请你返回这个数组的所有可能子集。
返回的答案中不能包含重复的子集,将答案按字典序进行排序。
方法一:
递归+剪枝
思路:递归回溯题型,先画图再写代码。
得到的每棵子树都是集合的子树。
注意:这里要剪枝,当前一个数等于当前数并且前一个数未访问过,则跳过该分支。
if(i>0&&nums[i]==nums[i-1]&&vis[i-1]==0)//剪枝 continue;
class Solution {
public:
vector<vector<int>> res;
int vis[15]={0};
vector<vector<int>> subsets(vector<int>& nums) {
sort(nums.begin(),nums.end());//排序
vector<int> v;
dfs(nums,0,v);//递归
return res;
}
void dfs(vector<int>& nums,int st,vector<int> &v){
res.push_back(v);//加入结果二维数组
int n=nums.size();
for(int i=st;i<n;i++){
if(i>0&&nums[i]==nums[i-1]&&vis[i-1]==0)//剪枝
continue;
v.push_back(nums[i]);
vis[i]=1;
dfs(nums,i+1,v);//递归回溯
v.pop_back();
vis[i]=0;
}
}
};
时间复杂度:
空间复杂度:![]()
方法二:
暴力递归(非剪枝)
思路:暴力递归。
利用一个无序set实现去重效果,忽略剪枝。
class Solution {
public:
vector<vector<int>> res;
int vis[15]={0};
unordered_set<string> mySet;//无序set
vector<vector<int>> subsets(vector<int>& nums) {
sort(nums.begin(),nums.end());//排序
vector<int> v;
dfs(nums,0,v);//递归
return res;
}
void dfs(vector<int>& nums,int st,vector<int> &v){
string str="";
for(int i=0;i<v.size();i++){
str+=v[i]+'0';
}
// cout << str << endl;
if(mySet.count(str)==0){//实现去重
res.push_back(v);//加入结果二维数组
mySet.insert(str);
}
int n=nums.size();
for(int i=st;i<n;i++){
v.push_back(nums[i]);
vis[i]=1;
dfs(nums,i+1,v);//递归回溯
v.pop_back();
vis[i]=0;
}
}
};
时间复杂度:
空间复杂度:![]()



京公网安备 11010502036488号