力扣 leetcode 90. 子集 II

问题描述

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10

示例

示例 1:

输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

解题思路

本题与力扣 leetcode 78. 子集有异曲同工之妙,但是本题多了一个限制,nums 中的元素现在已经可以重复了,这为我们去除结果中的重复元素带来了更大的挑战。

这里的一个思路是,可以用集合保存已有的结果,或者直接对现有的结果进行遍历,判断是否重复。但是,考虑到 nums[i] == nums[j],则 [nums[i], nums[j]] 和 [nums[j], nums[k]] 有时很难分辨出来。为此,我们可以对结果排序,或者对 nums 排序,保证结果是有序的,这样就方便判断结果是否重复。

因为现在结果已经有序,那我们只需判断结果中相同长度的子数组是否与现有结果相同,如果相同,则放弃此结果。

class Solution {
public:

    void pushItem(vector<int>& nums, vector<vector<int>>& res, vector<int>& r, int step, const int maxStep, int idx, int n){
        if(step){
            step--;
            for(int i = idx; i < nums.size() - step; i++){
                bool flag = true;
                for(int j = res.size() - 1; j >= 0 && res[j].size() == maxStep; j--){
                    if(nums[i] == res[j][n]){ // 判断结果中是否重复
                        flag = false;
                        for(int k = 0; k < n; k++){
                            if(r[k] != res[j][k]){
                                flag = true;
                                break;
                            }
                        }
                        break;
                    }
                }
                if(flag){
                    r[n] = nums[i];
                    pushItem(nums, res, r, step, maxStep, i + 1, n + 1);
                }
            }
        }
        else{
            vector<int> tmp(r);
            res.push_back(tmp);
        }
    }

    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        const int n = nums.size();
        vector<vector<int>> res(1, vector<int> {});
        int idx = 0;
        for(int i = 1; i <= n; i++){
            vector<int> r(i);
            pushItem(nums, res, r, i, i, idx, idx);
        }
        return res;
    }
};
posted @ 2022-12-07 23:05  greatestchen  阅读(14)  评论(0编辑  收藏  举报