90. Subsets II

经典题目,
跟LC78不一样的地方在于 (LC78见另外外一篇博文 https://www.jianshu.com/p/3b8fd52774f7)
这里有重复,需要去重。
LC78 版本二的解法关键在于不要回头看。这次要去重,要求就又苛刻些。
这次关键在于不仅不能回头看,如果你错过风景了,遇到相同的风景也不再收入囊中了。
先来的元素有优先权,如果你遇到一对完全相同的元素,双胞胎,如果你没取第一个却取了第二个,是不是就重复了? 所以你要么取第一个, 要么取第一个和第二个,要么哪个也不取,你不能只取第二个,这两个元素有尊卑。其实元素本身没有尊卑,但为了去重我们故意给他们按照先来后到的顺序标了优先级。
另外外一种理解方法是每一层只能取该层多胞胎中的第一个。

    public List> subsetsWithDup(int[] nums) {
        List> ans = new ArrayList<>();
        Arrays.sort(nums);
        subsetsWithDup(nums, 0, ans, new ArrayList<>());
        return ans;
    }
    private void subsetsWithDup(int[] nums, int index, 
                                List> ans, List curList ) {
        ans.add(new ArrayList<>(curList));
        for (int i = index; i < nums.length; i++) {
            if (i != index && nums[i] == nums[i - 1]) continue; //去重的关键在于此行
            curList.add(nums[i]);
            subsetsWithDup(nums, i + 1, ans, curList);
            curList.remove(curList.size() - 1);
        }
    }

C++版本

class Solution {
public:
    vector> subsetsWithDup(vector& nums) {
        sort(nums.begin(), nums.end());
        vector> ans;
        vector cur;
        dfs(nums, ans, 0, cur);
        return ans;
    }
private:
    void dfs(const vector& nums, vector>& ans, int index, vector& cur) {
        ans.emplace_back(cur);
        if (index == nums.size()) return;
        for (int i = index; i < nums.size(); i++) {
            if (i != index && nums[i] == nums[i - 1]) continue;
            cur.push_back(nums[i]);
            dfs(nums, ans, i + 1, cur);
            cur.pop_back();
        }
    }
};

注意请轻易不要使用class variable。

这题我尝试使用 https://www.jianshu.com/p/3b8fd52774f7 的第一个版本基础上增加去重功能, 发现比较麻烦,做倒是可以做。
假设你有5个5,就是要数一数已经取过的5和见过的5是不是数量相等。如果不相等,主不要取5了, 如果相等可以取5,也可以不取5,这个比较麻烦,不容易写的漂亮。

你可能感兴趣的:(90. Subsets II)