【LeetCode 78】子集

第一种:回溯解法

    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> answer=new ArrayList<>();
        if (nums == null || nums.length == 0) {
            return answer;
        }

        subsetsCore(nums,0,answer,new ArrayList<>());
        return answer;
    }

    public void subsetsCore(int[] nums, int index, List<List<Integer>> answer, List<Integer> currentAns) {
        answer.add(new ArrayList<>(currentAns));
        for(int i=index;i<nums.length;i++){
            currentAns.add(nums[i]);
            subsetsCore(nums,i+1,answer,currentAns);
            currentAns.remove(currentAns.size()-1);
        }
    }

第二种:暴力解法

从[]解集开始,扫描一遍元素,每扫描到一个元素就添加到当前所有解里面,同时原有解保持不变。

class Solution {
  public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> output = new ArrayList();
    output.add(new ArrayList<Integer>());

    for (int num : nums) {
      List<List<Integer>> newSubsets = new ArrayList();
      for (List<Integer> curr : output) {
        newSubsets.add(new ArrayList<Integer>(curr){{add(num);}});
      }
      for (List<Integer> curr : newSubsets) {
        output.add(curr);
      }
    }
    return output;
  }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/subsets/solution/zi-ji-by-leetcode/
来源:力扣(LeetCode)

第三种:递归解法

对元素的选择可以构成一颗二叉树,树根为第一个元素,左子树代表解集包含当前结点,右子树代表解集不包含当前结点,第二层是第二个元素...etc。从树的根结点向下递归搜索,即可获得所有子集。

    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> answer=new ArrayList<>();
        if (nums == null || nums.length == 0) {
            return answer;
        }

        subsetsCore(nums,0,answer,new ArrayList<>());
        return answer;
    }

    public void subsetsCore(int[] nums, int index, List<List<Integer>> answer, List<Integer> currentAns) {
        if(index>=nums.length){
            //最终将结果构建叶子结点存储到解集
            answer.add(new ArrayList<>(currentAns));
            return;
        }
        //这一步是为了构建中间结点,避免多个递归过程中修改同一个对象
        List<Integer> currentAnsTmp=new ArrayList<>(currentAns);
        subsetsCore(nums,index+1,answer,currentAnsTmp);
        currentAnsTmp.add(nums[index]);
        subsetsCore(nums,index+1,answer,currentAnsTmp);
    }

第四种:二进制映射方法求解

因为含有n个元素的集合的子集,正好相当于n个bit随机填充0或1的所有情况,也就是[0,2^n-1)的所有数值,每一个数值表示一个子集,数值bit为1表示元素在子集中。

class Solution {
  public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> output = new ArrayList();
    int n = nums.length;

    for (int i = (int)Math.pow(2, n); i < (int)Math.pow(2, n + 1); ++i) {
      // generate bitmask, from 0..00 to 1..11
      String bitmask = Integer.toBinaryString(i).substring(1);

      // append subset corresponding to that bitmask
      List<Integer> curr = new ArrayList();
      for (int j = 0; j < n; ++j) {
        if (bitmask.charAt(j) == '1') curr.add(nums[j]);
      }
      output.add(curr);
    }
    return output;
  }
}
来源:LeetCode

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值