题目:
给你一个整数数组 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] <= 10nums中的所有元素 互不相同
思路如下:
这道题是生成给定数字列表 nums 的所有可能子集。首先使用深度优先搜索(DFS)递归地构建每个子集。在每一步中,选择一个数字加入当前子集,或者跳过该数字。最后递归地处理下一个位置,直到所有可能的子集都被生成。
题解如下:
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
n = len(nums) # 获取数字列表的长度
ans = [] # 用于存储所有子集的列表
path = [] # 用于存储当前构建的子集
def dfs(i: int) -> None:
# 每次进入 dfs 时,将当前路径的副本添加到结果中
# 因为当前路径已经是一个有效的子集
ans.append(path.copy())
# 遍历从当前索引 i 开始的所有数字
for j in range(i, n):
# 将当前数字加入当前路径
path.append(nums[j])
# 递归调用 dfs,处理下一个位置
# 由于子集不能重复,所以从 j+1 开始
dfs(j + 1)
# 回溯,移除最后一个加入的数字,以便尝试其他选择
path.pop()
# 从第一个数字开始构建子集
dfs(0)
# 返回所有子集的结果
return ans
题解示例:
假设输入的数字列表为 [1, 2, 3]:
初始状态:
ans = []
path = []
递归过程:
从第一个数字开始(i = 0):
当前路径为空,添加到 ans:ans = [[]]。
选择 nums[0] = 1,path = [1]。
递归调用 dfs(1)。
在 i = 1 时:
当前路径为 [1],添加到 ans:ans = [[], [1]]。
选择 nums[1] = 2,path = [1, 2]。
递归调用 dfs(2)。
在 i = 2 时:
当前路径为 [1, 2],添加到 ans:ans = [[], [1], [1, 2]]。
选择 nums[2] = 3,path = [1, 2, 3]。
递归调用 dfs(3)。
i = 3,超出范围,返回。
回溯,path = [1, 2]。
回溯,path = [1]。
选择 nums[2] = 3,path = [1, 3]。
递归调用 dfs(3)。
i = 3,超出范围,返回。
回溯,path = [1]。
回溯,path = []。
选择 nums[1] = 2,path = [2]。
递归调用 dfs(2)。
在 i = 2 时:
当前路径为 [2],添加到 ans:ans = [[], [1], [1, 2], [1, 2, 3], [1, 3], [2]]。
选择 nums[2] = 3,path = [2, 3]。
递归调用 dfs(3)。
i = 3,超出范围,返回。
回溯,path = [2]。
回溯,path = []。
选择 nums[2] = 3,path = [3]。
递归调用 dfs(3)。
i = 3,超出范围,返回。
回溯,path = []。
最终结果:
ans 包含所有可能的子集:
[[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]
逻辑梳理:
- 初始化:
n:数字列表的长度。ans:存储所有子集的列表。path:当前构建的子集。
- 递归函数
dfs:- 参数
i:表示当前正在处理的数字的索引。 - 递归终止条件:
- 每次调用
dfs时,都将当前路径path的副本添加到ans中。
- 每次调用
- 递归过程:
- 遍历从当前索引
i开始的所有数字。 - 将当前数字加入
path。 - 递归调用
dfs(j + 1),处理下一个位置。 - 在递归返回后,从
path中移除最后一个数字(回溯)。
- 遍历从当前索引
- 参数
- 回溯:
- 在每次递归返回后,恢复当前状态,以便尝试其他可能的子集。
&spm=1001.2101.3001.5002&articleId=147144102&d=1&t=3&u=ba60c8e7524142cba8f6d7abff9e6148)
496

被折叠的 条评论
为什么被折叠?



