📘题目描述
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0] 输出:[[],[0]]
💡解题思路:回溯法(Backtracking)
🧠核心思想
-
子集问题的本质是在每个元素面前做“选”或“不选”
-
使用回溯法逐步构造出所有可能的组合
-
使用参数
start
控制从哪里开始选数字,确保不重复、不回头
✅Python 实现
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
def backtrack(start, path):
res.append(path[:])
for i in range(start, len(nums)):
# start 是用来控制递归中从哪里开始选数字的
# 避免重复、保证子集不重复,且不回头选择已经处理过的元素。
path.append(nums[i])
backtrack(i + 1, path)
path.pop()
backtrack(0, [])
return res
⏱️复杂度分析
项目 | 复杂度 | 说明 |
---|---|---|
时间复杂度 | O(n × 2ⁿ) | 每个元素有选/不选两种状态,共 2ⁿ 个子集,每个子集最多 n 个元素 |
空间复杂度 | O(n) | 递归栈最大深度为 n |
🧱常见易错点
错误点 | 正确做法说明 |
---|---|
没有复制 path | 要用 path[:] 添加子集副本 |
忘记 start 控制递归范围 | start 确保不重复选择已处理过的元素 |
误把子集当作排列处理 | 子集不需要考虑顺序,只控制是否选入即可 |
🔁扩展解法(非递归二进制法)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
for mask in range(1 << n):
subset = []
for i in range(n):
if mask & (1 << i):
subset.append(nums[i])
res.append(subset)
return res
这种解法将每个子集映射为一个 n
位二进制数,1
表示选,0
表示不选。
🎯总结
-
本题是回溯入门题,属于组合型问题。
-
建议掌握两种方法:
-
✅ 回溯(递归)
-
✅ 位运算(非递归)
-