Typescript-Algorithms
    Preparing search index...

    Variable sub_setsConst

    sub_sets: (nums: number[]) => number[][] = subsets

    78.子集

    给你一个整数数组 nums,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

    解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。


    输入: nums = [1,2,3]

    输出: [[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]


    输入: nums = [0]

    输出: [[],[0]]


    • 1 <= nums.length <= 10
    • -10 <= nums[i] <= 10
    • nums 中的所有元素 互不相同

    Type declaration

      • (nums: number[]): number[][]
      • Parameters

        • nums: number[]

        Returns number[][]

    回溯算法

    1. 当前操作?
    2. 子问题?
    3. 下一个子问题?
    • 子集型回溯:每个元素都可以选或者不选。要生成子集有两种思路,区别在于当前操作是什么:

      • 输入角度:dfs(i)从下标>=i的数字中构造子集

        • 当前操作:枚举第i个数选/不选
        • 子问题:从下标>=i的数字中构造子集
        • 下一个子问题:从下标>=i+1的数字中构造子集。dfs(i) -> dfs(i+1)
        • 特点
          • 每个元素都可以“选”或“不选”,所有组合都能被枚举到。
          • 递归树是“二叉树”结构。
          • 不需要考虑顺序和去重问题,因为每个元素的选/不选都被单独处理。
      • 输出角度:子集问题不考虑顺序,为了避免重复我们就规定顺序,让它严格递增

        • 当前操作:每次必须选一个数。枚举下标j>=i的数字,加入path

        • 子问题:从下标>=i的数字中构造子集

        • 下一个子问题:从下标>=j+1的数字中构造子集。

        • 特点

          • 每次递归都可以选“后面所有还没选过的数”,保证了组合的顺序递增(避免重复)。

          • 递归树是“多叉树”结构。

          • 这种写法天然避免了重复子集(比如 [1,2] 和 [2,1] 只会出现 [1,2])。

      角度 递归树结构 适用场景 去重方式
      输入角度 二叉树 子集、选/不选 不需要特判
      输出角度 多叉树 组合、顺序无关 通过递增下标去重
    • 组合型回溯

    • 排列型回溯:进入每层都使用一个新的辅助set用来存储当前层能够候选的数有哪些。

    • 定长可以使用数组,path[i]本身能够覆盖旧元素,相当于恢复现场
    // 枚举答案的每一个数的角度 (子集型回溯)
    function subsets(nums: number[]): number[][] {
    const ans: number[][] = [];
    const path: number[] = [];

    function dfs(i: number) {
    ans.push([...path]);

    for (let j = i; j < nums.length; j++) {
    path.push(nums[j]);
    dfs(j + 1);
    path.pop();
    }
    }

    dfs(0);

    return ans;
    };

    // 选或者不选的角度 (子集型回溯)
    function subsets2(nums: number[]): number[][] {
    const path: number[] = [];
    const ans: number[][] = [];

    function dfs(i: number) {
    if (i === nums.length) {
    ans.push([...path]);
    return;
    }

    dfs(i + 1);

    path.push(nums[i]);
    dfs(i + 1);
    path.pop();
    }

    dfs(0);

    return ans;
    }