文章目录
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
nums 中的所有元素 互不相同
思路:
数组里每个元素只有两种选择:
- 选这个元素
- 不选这个元素
递归就是逐个处理数组元素,对每个元素都做这两种选择,直到处理完所有元素,把当前的子集存起来。
代码实现(Go):
go
package main
import "fmt"
// subsets 求数组所有子集
func subsets(nums []int) [][]int {
// 保存最终答案
var ans [][]int
// 保存当前正在拼接的子集
var path []int
// 定义递归函数:cur 表示现在处理第几个数字
var dfs func(cur int)
dfs = func(cur int) {
// 递归终止:所有数字都处理完了
if cur == len(nums) {
// 把当前子集复制一份,加入答案
ans = append(ans, append([]int{}, path...))
return
}
// ==================== 两个选择 ====================
// 选择1:选当前数字 → 加入path → 继续下一个
path = append(path, nums[cur])
dfs(cur + 1)
// 选择2:不选当前数字 → 回退(删掉最后一个)→ 继续下一个
path = path[:len(path)-1]
dfs(cur + 1)
}
// 从第0个数字开始递归
dfs(0)
return ans
}
func main() {
fmt.Println(subsets([]int{1, 2, 3})) // [[] [3] [2] [2 3] [1] [1 3] [1 2] [1 2 3]]
fmt.Println()
fmt.Println(subsets([]int{0})) // [[] [0]]
}
时间复杂度:O(n × 2ⁿ)
- 数组长度
n,总共有 2ⁿ 个子集(每个元素选/不选) - 每个子集需要复制一次,复制耗时 O(n)
- 总时间:n × 2ⁿ
空间复杂度:O(n)
- 递归调用栈深度 = 数组长度
n - 临时子集
current最大长度 = n - 结果存储空间不算额外空间(题目要求必须输出)