算法:回溯十一 Subsets数组的子数组集合4种解法

题目

地址:https://leetcode.com/problems/subsets/

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:

Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

1. DFS深度优先回溯解法

思路解析:

  1. 遍历数组中的元素,要么选择,要么不选择。
  2. 注意退出条件即可if (nums == null || index == nums.length) 。表示可能数组为空,可能index已经越界,则添加到结果列表中。
package backtracking;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

// https://leetcode.com/problems/subsets/
public class Subsets {

  public static void main(String[] args) {
    int[] nums = new int[]{1,2,3};
    Subsets obj = new Subsets();
    List<List<Integer>> resultList = obj.subsets(nums);
    System.out.println(Arrays.toString(resultList.toArray()));
  }

  public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> resultList = new ArrayList<List<Integer>>();
    // dfs
    dfs(nums, resultList, new ArrayList<Integer>(), 0);

    return resultList;
  }

  private void dfs(int[] nums, List<List<Integer>> resultList, List<Integer> list, int index) {
    // exit
    if (nums == null || index == nums.length) {
      resultList.add(new ArrayList<Integer>(list));
      return;
    }

    // add item
    list.add(nums[index]);
    dfs(nums, resultList, list, index + 1);

    // not add item
    list.remove(list.size() - 1);
    dfs(nums, resultList, list, index + 1);
  }
}

2. 遍历执行

从一个空列表List<List<Integer>> outputList开始,添加一个空列表new ArrayList<Integer>(),遍历所有数据(比如:{1, 2, 3}),

  1. 新建一个空列表List<List<Integer>> newList,
  2. 遍历列表List<List<Integer>> outputList,把已有子项都添加上新的数字,
比如遍历到1[ ] > [1]
比如遍历到2[ ] > [2]
[1] > [1, 2]
  1. 遍历列表new ArrayList<Integer>(),把新生成的子列表追加到已有列表的后面List<List<Integer>> outputList
    在这里插入图片描述
public List<List<Integer>> subsetsWithRecursion(int[] nums) {
  List<List<Integer>> outputList = new ArrayList<List<Integer>>();
  outputList.add(new ArrayList<Integer>());
  for (int num: nums) {
    List<List<Integer>> newList = new ArrayList<List<Integer>>();
    for (List<Integer> list: outputList) {
      newList.add(new ArrayList<Integer>(list) {{ add(num); }});
    }

    for (List<Integer> list: newList) {
      outputList.add(list);
    }
  }

  return outputList;
}

3. 回溯解法,达到指定长度就返回

在这里插入图片描述

public List<List<Integer>> subsetsWithBacktrack(int[] nums) {
  List<List<Integer>> resultList = new ArrayList<List<Integer>>();
  for (int len = 0; len <= nums.length; len++) {
    // backtrack
    backtrack(nums, resultList, new ArrayList<Integer>(), 0, len);
  }

  return resultList;
}

private void backtrack(int[] nums, List<List<Integer>> resultList, List<Integer> list, int first, int len) {
  // exit
  if (list.size() == len) {
    resultList.add(new ArrayList<Integer>(list));
    return;
  }

  if (first == nums.length) {
    return;
  }
  list.add(nums[first]);
  backtrack(nums, resultList, list, first + 1, len);
  list.remove(list.size() - 1);
  backtrack(nums, resultList, list, first + 1, len);
}

4. 二进制位组装

算法思想来自 Donald E.Knuth. 组装成跟数组长度一样的二进制,如果为1则添加进来,否则就不添加。
在这里插入图片描述

public List<List<Integer>> subsetsWithBinarySorted(int[] nums) {
    List<List<Integer>> resultList = new ArrayList<List<Integer>>();
    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> list = new ArrayList<Integer>();
      for (int k = 0; k < n; k++) {
        if (bitmask.charAt(k) == '1') {
          list.add(nums[k]);
        }
      }

      resultList.add(list);
    }

    return resultList;
  }

代码下载

https://github.com/zgpeace/awesome-java-leetcode/blob/master/code/LeetCode/src/backtracking/Subsets.java

参考

https://leetcode.com/problems/subsets/solution/

https://www-cs-faculty.stanford.edu/~knuth/taocp.html

发布了127 篇原创文章 · 获赞 12 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zgpeace/article/details/103855352
今日推荐