78. 子集

leecode原题

题目

给你一个整数数组 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
  • nums 中的所有元素 互不相同

解题思路

思路

如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!

其实子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。

那么既然是无序,取过的元素不会重复取,写回溯算法的时候,for就要从startIndex开始,而不是从0开始!

以示例中nums = [1,2,3]为例把求子集抽象为树型结构,如下:

从图中红线部分,可以看出遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合。

关键点:

  • 剩余集合为空的时候,就是叶子节点。
  • 求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。

实现

源码

var (
    res  = make([][]int, 0) // 存放最终结果
    path = make([]int, 0)   // 存放中间结果
)

func backtracking(nums []int, startIndex int) {
    // 收集子集,要放在终止添加的上面,否则会漏掉自己
    temp := make([]int, len(path))
    copy(temp, path)
    res = append(res, temp)

    if startIndex >= len(nums) { // 可以不加, for循环会自动退出
        return
    }
    for i := startIndex; i < len(nums); i++ {
        path = append(path, nums[i])
        backtracking(nums, i+1)
        path = path[:len(path)-1]
    }
}

func subsets(nums []int) [][]int {
    res = make([][]int, 0)
    path = make([]int, 0)
    backtracking(nums, 0)
    return res
}
Copyright © ROSEMARY666 2022 all right reserved,powered by Gitbook该文章修订时间: 2022-09-28 15:55:21

results matching ""

    No results matching ""