【leetcode】90. Subsets II

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





你可能感兴趣的:(LeetCode,DFS,Subsets)