1. 程式人生 > 實用技巧 >【Important】78.子集

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