78. 子集
文章目录
-
- [78. 子集(https://leetcode.cn/problems/subsets/)](#78. 子集)
- [- 回溯法](#- 回溯法)
- 结语
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
text
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
text
输入:nums = [0]
输出:[[],[0]]
思路
- 这道题和全排列一样,都是递归的经典题,但子集比全排列多了一个"顺序无关"的限制。全排列里
[1,2]和[2,1]是两个答案,但子集里它们是同一个。所以这道题递归的核心就变成了:怎么保证下一层只从当前位置往后选。下面用回溯法写一下
- 回溯法
-
这里我们用闭包的方式,不需要传结果集的指针
-
使用到的参数有
- ans 用来记录结果集
- path 当前子集
- start 下一层枚举的起点
-
go
gofunc subsets(nums []int) [][]int { ans := make([][]int, 0) path := make([]int, 0) length := len(nums) var dfs func(start int) dfs = func(start int) { //每进入一层,当前 path 就是一个合法子集 tmp := append([]int(nil), path...) ans = append(ans, tmp) //从 start 开始枚举,保证顺序不重复 for i := start; i < length; i++ { path = append(path, nums[i]) dfs(i + 1) //回溯 path = path[:len(path)-1] } } dfs(0) return ans } -
还有一个容易踩的坑:ans = append(ans, path) 这样写是错的,因为 path 是复用的切片,后续 append 和截断会改到底层数组。必须像上面那样拷贝一份 tmp 再存
结语
本文是 《算法题目解析系列》 的第 34 篇,本系列将持续更新,每篇都提供清晰的思路与编程语言实现。欢迎关注,第一时间获取更新。如果你有想看的题目,也可以在评论区留言告诉我。