LeetCode90. Subsets II(C++)

Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:

Input: [1,2,2]
Output:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

解題思路:與78題不同,本題可能存在相同的元素,如何刪除相同的集合則是本題的難點。

以[1,2,2]爲例,以78解題思路(回溯剪枝),得到子集的順序爲[[],[1],[1,2],[1,2,2],[1,2],[2],[2,2],[2]],相當於先找到第一個元素構成的所有子集,再找第二個元素構成的子集,由此類推,如果繼續採用這種思路,在剔除的時候會有點麻煩。

本題用另外一種思路,與78題中的非遞歸解法一致,從最終結果來看,求得子集順序爲[[],[1],[2],[1,2],[2],[1,2],[2,2],[1,2,2]],即先求元素個數爲0的子集,接着求個數爲1的子集,由此類推,具體做法如下:

先將nums排序,來保證所有相同的元素在一起,設一個ans數組記錄已經有的子集,將空集壓入。

壓入1:調出空集,將1壓入得到[[],[1]]

壓入2:首先調出[],得到[2],再調出[1],得到[1,2],當前結果爲[[],[1],[2],[1,2]]。

壓入第二個2:從第二次得出的子集,依次再在每個子集中壓入2,最終得到[[],[1],[2],[1,2],[2],[1,2],[2,2],[1,2,2]]

此即爲78題非遞歸的解法,如果要用於本題,在壓入第二個2的時候,需要去除[[],[1],[2],[1,2]]中不含有第一個2的子集,在剩下的子集中壓入第二個2。換言之,需要修改left。

當此時num的值與上一次遍歷的值一致,left應該爲壓入上一個num值前的子集個數。

class Solution {
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>>ans;
        vector<int>tempans;
        ans.push_back(tempans);
        int right = 1, left = 0, len = 0;
        for(int i = 0; i < nums.size(); ++ i){
            if(i != 0 && (nums[i] == nums[i-1]))
                left = ans.size() - len;
            else
                left = 0;
            right = ans.size();
            len = right - left;
            for(int j = left; j < right; ++ j){
                tempans = ans[j];
                tempans.push_back(nums[i]);
                ans.push_back(tempans);
            }
        }
        return ans;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章