【玩转回溯算法专题】90. 子集 II 【中等】

【玩转回溯算法专题】90. 子集 II 【中等】

1、力扣链接

https://leetcode.cn/problems/subsets-ii/submissions/552551584/

2、题目描述

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

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

示例 1:

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

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

提示:

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

3、题目分析

回溯三部曲

1、递归函数参数
首先是题目给的nums[],for循环的起始值startIndex
2、递归终止条件
涉及去重,首先对nums数组排序,并定义一个used[]数组,用来记录nums[]的元素是否被使用过,也就是以第二个 2开始 作为第一个元素去进入for循环逻辑,是无用的,因为会重复

//当i>0 并且 两个相邻元素相等比如 【1 2 2】中 的2 2 现在遍历到第二个 2 时,且当前元素该轮次没有被使用过 
if(i > 0 && nums[i] == nums[i-1] && !used[i-1]){
                continue;
            }

3、单层搜索逻辑

//将元素加入path
path.add(nums[i]);
//该元素正在被使用
used[i] = true;
backing(nums,i+1);
path.removeLast();
used[i] = false;

1、Java

class Solution {
//回溯三部曲
//1、确定返回值
//2、确定终止条件
//3、单层for循环处理逻辑
    List<List<Integer>> res = new ArrayList();
    List<Integer> path = new ArrayList();
    boolean[] used;

    public List<List<Integer>> subsetsWithDup(int[] nums) {
        if(nums.length == 0){
            res.add(path);
            return res;
        }
        Arrays.sort(nums);
        //重复元素
        used = new boolean[nums.length];
        backing(nums,0);

        return res;


    }

    public void backing(int[] nums,int startIndex){
            res.add(new ArrayList(path));
            if(startIndex >= nums.length){
                return;
            }
    
        for(int i=startIndex;i<=nums.length-1;i++){
            if(i > 0 && nums[i] == nums[i-1] && !used[i-1]){
                continue;
            }
            path.add(nums[i]);
            used[i] = true;
            backing(nums,i+1);
            path.removeLast();
            used[i] = false;
        }
    }
}

2、C++

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(vector<int>& nums, int startIndex) {
        result.push_back(path);
        for (int i = startIndex; i < nums.size(); i++) {
            // 而我们要对同一树层使用过的元素进行跳过
            if (i > startIndex && nums[i] == nums[i - 1] ) { // 注意这里使用i > startIndex
                continue;
            }
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }

public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        result.clear();
        path.clear();
        sort(nums.begin(), nums.end()); // 去重需要排序
        backtracking(nums, 0);
        return result;
    }
};
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值