90. 子集 II【Normal】【回溯】

给你一个整数数组 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


思路:

1. 对数组,先排序

2. 回溯

3. 去重


解答:

/**
 * @param {number[]} numArr
 * @return {number[][]}
 */
var subsetsWithDup = function(numArr) {
    // 1.必须先排序
    numArr.sort((a, b) => {
        // 升序
        return a - b;
    })
    
    let res = [];
    let path = [];
    let startIndex = 0;
    
    // 2.回溯
    backtrack(numArr, startIndex, path, res);
    
    // 3.结果数组去重
    let tmp = [];
    let set = new Set();
    for(let path of res){
        if(!set.has(path.toString())){
            set.add(path.toString());
            tmp.push(path);
        }
    }
    return tmp;
};

function backtrack(numArr, startIndex, path, res){
    // 没有递归终点
    res.push([...path]);
    
    // 遍历所有选择
    let len = numArr.length;
    for(let i = startIndex; i < len; i++) {
        let num = numArr[i];
        // 由于有重复的,所以有两种选择:选它或者不选它
        // 1. 而且必须是选它 在前面
        // 作出选择
        path.push(num);
        // 进入下一层
        backtrack(numArr, i + 1, path, res);
        // 撤销选择
        path.pop();
        
        // 2. 然后才是 不选它,并且要跳过后面和它一样的数字
        while(i < len && numArr[i] === num){
            i++;
        }
        // 进入下一层
        backtrack(numArr, i, path, res);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
子集和问题是一个经典的组合问题,给定一个正整数集合和一个目标值,找出集合中若干个数的和等于目标值。这个问题可以使用回溯算法来解决。 回溯算法的思路是,在搜索过程中维护一个当前的集合和当前的和,从集合中选择一个数加入集合,如果加入后集合的和等于目标值,就找到了一组解;否则继续选择下一个数加入集合,直到遍历完所有的选择或者集合的和已经超过了目标值,此时需要回溯到上一个状态,重新选择下一个数加入集合。 具体的实现可以使用递归函数来完成。递归函数的参数包括当前的集合、当前的和、目标值、集合中数的起始下标。在递归函数中,首先判断当前集合的和是否等于目标值,如果是则找到了一组解,否则继续向下搜索。在搜索过程中,维护一个变量表示当前集合的和,然后选择一个数加入集合,更新集合和,递归调用自身,搜索下一个数,直到遍历完所有的选择。 代码如下: ```python def subset_sum(nums, target): res = [] def backtrack(subset, start, cur_sum): if cur_sum == target: res.append(subset[:]) elif cur_sum < target: for i in range(start, len(nums)): subset.append(nums[i]) cur_sum += nums[i] backtrack(subset, i+1, cur_sum) subset.pop() cur_sum -= nums[i] backtrack([], 0, 0) return res ``` 这个算法的时间复杂度是指数级别的,因为在搜索过程中每个数都有选或不选两种选择,所以总共有 $2^n$ 种情况需要搜索,其中 $n$ 是集合中数的个数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值