总结一下,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; } };
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; } };