Leetcode 78. Subsets

在这里插入图片描述
方法1: dp。就是找规律,具体思路解释可以看lc官方解释1,说得还是挺明白的。这个方法需要注意的是deep copy这个问题,我自己的代码是用loop来copy list的,但是lc官方答案里面没用这个方法,我不知道为什么,复盘的时候要去看一下lc方法1的代码和我自己的区别在哪里。时间复杂n*2的n次方,空间复杂same。

// 我的代码 
class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if(nums.length == 1) {
            res.add(new ArrayList<>());
            res.add(new ArrayList<>());
            res.get(1).add(nums[0]);
            return res;
        }
        List<List<Integer>> list1 = subsets(Arrays.copyOfRange(nums, 0, nums.length - 1));
        List<List<Integer>> list2 = new ArrayList<>();
        int curr = nums[nums.length-1];
        for(List<Integer> l : list1){
            res.add(l);
            List<Integer> temp = new ArrayList<>();
            for(Integer i : l) temp.add(i);
            list2.add(temp);
        } 
        for(List<Integer> l : list2){
            l.add(curr);
            res.add(l);
        }
        return res;
    }
}
// lc方法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;
  }
}

方法2: backtracking,不是很好理解。我暂时不要求自己掌握。时间复杂空间复杂同方法1.

class Solution {
  List<List<Integer>> output = new ArrayList();
  int n, k;

  public void backtrack(int first, ArrayList<Integer> curr, int[] nums) {
    // if the combination is done
    if (curr.size() == k)
      output.add(new ArrayList(curr));

    for (int i = first; i < n; ++i) {
      // add i into the current combination
      curr.add(nums[i]);
      // use next integers to complete the combination
      backtrack(i + 1, curr, nums);
      // backtrack
      curr.remove(curr.size() - 1);
    }
  }

  public List<List<Integer>> subsets(int[] nums) {
    n = nums.length;
    for (k = 0; k < n + 1; ++k) {
      backtrack(0, new ArrayList<Integer>(), nums);
    }
    return output;
  }
}

方法3: bit manipulation。这是一个非常巧妙的方法,详细解释见lc官方解答3,说得很清楚。这个方法一定要掌握,我现在没有自己实现,复盘记得要自己实现一下。时间复杂空间复杂同上两个方法。

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;
  }
}

总结:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值