总结一下,leetcode Subsets II ,题目的意思是得到一个含有重复元素的集合的所有子集。
下面分别给出3种解法。
1. dfs. 该解法16ms beats 17.33% of cpp submissions.
class Solution {
public:
void dfs(int idx, vector<int>& tmp, vector<vector<int>>& ans, vector<int>& nums){
ans.push_back(tmp);
// for循环的关键是,对于下一个与当前元素相同的元素,都需要跳过
// 也就是 1, 1, 1, 2, 2, 3, 4, 4. 最终这个for循环只能遍历1, 2, 3, 4.
for(int i = idx; i < nums.size(); ++ i) {
if(i && i > idx && nums[i] == nums[i-1]) continue;
tmp.push_back(nums[i]);
dfs(i+1, tmp, ans, nums);
tmp.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> ans;
if(nums.size() < 1) return ans;
// 首先排序
sort(nums.begin(), nums.end());
vector<int> tmp;
dfs(0, tmp, ans, nums);
return ans;
}
};
2. map + dfs, 本质上与第一种解法相同,因为map将所有的相同的元素都几种在一个对应关系上,这样就可以直接只遍历一个元素。该解法 8ms beats 75.43% of cpp submissions.
class Solution {
public:
void dfs(vector<int>& tmp, vector<vector<int>>& ans, map<int, int>& nmap, map<int, int>::iterator begin){
ans.push_back(tmp);
for(map<int, int>::iterator iter = begin; iter != nmap.end(); ++ iter) {
if(iter->second){
tmp.push_back(iter->first);
(iter->second) --;
dfs(tmp, ans, nmap, iter);
(iter->second) ++;
tmp.pop_back();
}
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> ans;
if(nums.size() < 1) return ans;
map<int, int> nmap;
for(int i = 0; i < nums.size(); ++ i) {
nmap[nums[i]] ++;
}
vector<int> tmp;
dfs(tmp, ans, nmap, nmap.begin());
return ans;
}
};
3. 利用之前已有的序列,不断的对已有序列进行填充。如 1, 1, 2, 3, 3, 5. ans中初始化的结果是一个空集[]
对于1,1 取出[], 将[1], [1, 1]分别和[]合并,压入结果序列,此时结果序列ans为[], [1], [1,1]
对于2, 取出[], [1], [1,1], 此时将[2]与前3者合并,结果为[2], [1, 2], [1, 1, 2],加入结果序列ans, 此时结果为[], [1], [1, 1], [2], [1, 2], [1, 1, 2]。
......以此类推。该解法:12ms, beats 22.32% of cpp submissions
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> ans;
if(nums.size() < 1) return ans;
map<int, int> nmap;
for(int i = 0; i < nums.size(); ++ i) {
nmap[nums[i]] ++;
}
ans.push_back(vector<int>());
map<int, int>::iterator iter = nmap.begin();
while(iter != nmap.end()) {
int cnt = iter->second;
int previousN = ans.size();
for(int j = 0; j < previousN; ++ j) {
vector<int> tmp = ans[j];
for(int k = 0; k < cnt; ++ k) {
tmp.push_back(iter->first);
ans.push_back(tmp);
}
}
++ iter;
}
return ans;
}
};
与此题类似的题目有 78.subsets 77.combinations