LeetCode-子集2(回溯+递归)

(一)题目描述

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

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

(二) 解题思路

        利用回溯+递归,该题与单纯求子集有所不同,该题所给集合有重复元素,所以所得结果就涉及去重问题。去重分两种:第一,树层去重(就是该题):即同一层的元素不能重复选取,基本去重思想即如果nums[i]==nums[i-1]&&flag[i-1]=false(该句话的含义即为:如果同一层元素有相同的,那么在选取同一层的下一个元素时,同层党的上一个元素必定刚出栈,所以其标志为false,若为同树枝的不同层元素,因下一个元素被选择时上一个元素不必出栈,所以其标志为true)

(三)代码实现

class Solution28 {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        ArrayList path = new ArrayList<>();
        Arrays.sort(nums);
        int len=nums.length;
        boolean[] flag=new boolean[len];
        dfs(nums,res,path,0,len,flag);
        return res;
    }
    public void dfs(int[] nums,List<List<Integer>> res,ArrayList path,int k,int len,boolean[] flag){
        //每递归一次,就将上一次得到的新的路径加入到res中
        res.add(new ArrayList<>(path)); //复制一份path数组,并加入res中
//       如果已经遍历到数组尾部,则回退
        if(k==len){
            return;
        }
        for (int i = k; i < len; i++) {
//            如果同一层有重复元素,则剪枝
            if(i>=0&&nums[i]==nums[i-1]&&flag[i]==false){
                continue;
            }
            //添加元素进路径并标记
            path.add(nums[i]);
            flag[i]=true;
            dfs(nums,res,path,i+1,len,flag);
            //递归回退,恢复到递归前的状态
            flag[i]=false;
            path.remove(path.size()-1);
        }
    }
}

补充知识点:

res.add(new ArrayList<>(path));//添加path的副本到res,下一次path的改变不会影响res数组
res.add(path);//添加path到res数组,path的改变会影响res数组中原来添加的path的值,如path={1,2,3},添加后res={{1,2,3}},之后path变为{1,2,3,4},则再添加一次path后,res变为{{1,2,3,4},{1,2,3,4}},而上面的写法res为{{1,2,3},{1,2,3,4}}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值