【Important】78.子集

78.子集

给你一个整数数组 nums ,返回该数组所有可能的子集(幂集)。解集不能包含重复的子集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:

输入:nums = [0]
输出:[[],[0]]
 

提示:

1 <= nums.length <= 10
-10 <= nums[i] <= 10

该题目为非常标准的dfs问题,用于了解最基本的dfs算法
算法核心:每个数字有可能或者不出现在解中 以该核心衍生出四种不同的算法

1、标准dfs

这里给出dfs算法模板 同时会记录与算法专栏-模板中

ArrayList<int> t;
ArrayList<ArrayList<int>> res;
public void dfs(int pos, int length) {
    if (pos == length) { //如果当前指针超过了数组索引 则为一个完整的解 返回
        // res.add(new ArrayList<>(t));
        return;
    }
    // 考虑选择当前位置
    t.add(nums[pos]);
    dfs(pos + 1, length); // 当前位置出现在解中
    t.remove(t.size() - 1);
    // 考虑不选择当前位置
    dfs(pos + 1, length); //当前位置不出现在解中
}

因此 本题标准解为

class Solution {
    ArrayList<List<Integer>> res  = new  ArrayList<List<Integer>>();
    ArrayList<Integer> temp = new ArrayList<>(); 
    public List<List<Integer>> subsets(int[] nums) {
        int n = nums.length;
        dfs(nums, 0, n);
        return res;
    }
    public void dfs (int[] nums, int pos, int len){
        if (pos == len){
            res.add(new ArrayList<>(temp));
            return;
        }
        temp.add(nums[pos]);
        dfs(nums, pos + 1, len);
        temp.remove(temp.size() - 1);
        dfs(nums, pos+1, len);
    }
}

2、树的中序遍历

1的题解本质思想其实就是一颗二叉树,数字左右节点分别代表取 或者 不取 在当前位置上的值,所有叶子节点构成了解集。
因此在做dfs的题时,将抽象的概念具体化成树有助于理解题目

3、位运算

本题的核心的另一种解读:将每个数字出现与否转换为位上是否为1


class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        ArrayList<List<Integer>> res  = new  ArrayList<List<Integer>>();
        List<Integer> temp = new ArrayList<>();
        int n = nums.length;
        for (int mask = 0; mask < (1 << n); mask++){
            temp.clear();
            for (int i = 0; i < n;i++){
                if (( (1 << i) & mask ) != 0) temp.add(nums[i]);
            }
            res.add(new ArrayList(temp));

        }
        return res;
    }

}

4、遍历添加法

需要一些技巧才能想出来的解法,本质上是从核心部分推出来的解法

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        ArrayList<List<Integer>> res  = new  ArrayList<List<Integer>>();
        List<Integer> temp = new ArrayList<>();
        res.add(new ArrayList<Integer>());
        int n = nums.length;
        for (int i = 0; i < n; i++){
            int value = nums[i];
            int currentSize = res.size();
            for (int j = 0; j < currentSize;j++){
                List<Integer> currentList = new ArrayList(res.get(j));
                currentList.add(value);
                res.add(currentList);
            }
        }
        return res;
    }
}
posted @ 2021-01-10 16:23  backTraced  阅读(52)  评论(0)    收藏  举报