78 子集
题目描述: 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明: 解集不能包含重复的子集。
思路: dfs回溯。
class Solution {
public:
void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, vector<int>& flag, int pos, int mx) {
ans.push_back(tmp);
if(pos == nums.size())
return ;
for(int i = mx; i < nums.size(); i++) {
// if(flag[i] == 0) {
tmp.push_back(nums[i]);
flag[i] = 1;
dfs(nums, ans, tmp, flag, pos + 1, i + 1);
tmp.pop_back();
flag[i] = 0;
// }
}
}
vector<vector<int>> subsets(vector<int>& nums) {
// sort(nums.begin(), nums.end());
vector<vector<int>> ans;
vector<int> tmp;
vector<int> flag(nums.size(), 0);
dfs(nums, ans, tmp, flag, 0, 0);
return ans;
}
};
90 子集2
题目描述: 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明: 解集不能包含重复的子集。
思路: 与78题的不同在于本题中整数数组nums中包含重复元素, 所以在回溯算法中可能会出现重复子集的结果,需要考虑对子集去重: 首先对nums排序,然后用map标记去重。
class Solution {
public:
void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, map<vector<int>,int>& mp, vector<int>& flag, int pos, int mx) {
if(mp[tmp] == 0) {
ans.push_back(tmp);
mp[tmp] = 1;
}
if(pos == nums.size())
return ;
for(int i = mx; i < nums.size(); i++) {
if(flag[i] == 0) {
tmp.push_back(nums[i]);
flag[i] = 1;
dfs(nums, ans, tmp, mp, flag, pos + 1, i + 1);
tmp.pop_back();
flag[i] = 0;
}
}
return ;
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
vector<int> tmp;
map<vector<int>, int> mp;
vector<int> flag(nums.size(), 0);
dfs(nums, ans, tmp, mp, flag, 0, 0);
return ans;
}
};
46 全排列
题目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列。
思路: dfs回溯。
class Solution {
public:
void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, vector<int>& flag, int cnt) {
if(cnt == nums.size()) {
ans.push_back(tmp);
return ;
}
for(int i = 0; i < nums.size(); i++) {
if(flag[i] != 0)
continue;
tmp.push_back(nums[i]);
flag[i] = 1;
dfs(nums, ans, tmp, flag, cnt + 1);
tmp.pop_back();
flag[i] = 0;
}
return ;
}
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> ans;
vector<int> tmp;
vector<int> flag(nums.size(), 0);
dfs(nums, ans, tmp, flag, 0);
return ans;
}
};
47 全排列2
题目描述: 给定一个可包含重复数字的序列,返回所有不重复的全排列。
思路: 根据46题思路,用dfs回溯。不同点在于序列中包含可重复数字,需要考虑去重问题。可以采用map标记去重,但当序列规模较大时,时间复杂度大。去重思路同组合总和2(#40题)—思路3。
class Solution {
public:
void dfs(vector<int>& nums, vector<vector<int>>& ans, vector<int>& tmp, vector<int>& flag, int cnt) {
if(cnt == nums.size()) {
ans.push_back(tmp);
return ;
}
for(int i = 0; i < nums.size(); i++) {
if(flag[i] != 0)
continue;
if(i != 0 && nums[i] == nums[i - 1] && flag[i - 1] == 0)
continue;
tmp.push_back(nums[i]);
flag[i] = 1;
dfs(nums, ans, tmp, flag, cnt + 1);
tmp.pop_back();
flag[i] = 0;
}
return ;
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
vector<int> tmp;
vector<int> flag(nums.size(), 0);
// map<vector<int>, int> mp;
dfs(nums, ans, tmp, flag, 0);
return ans;
}
};