解法
- 思想:迭代、递归/回溯
- 迭代法:思想是,每增加一个数,新增加的子集跟已有子集关系密切,具体如下
- 令nums=[0,1,2],观察[0,1]增加2后子集的变化
- nums的子集为[ [ ], [0], [1], [0, 1], [2], [0,2], [1,2], [0,1,2] ]
- 令nums1=[0,1],子集为[ [ ], [0], [1], [0,1] ],与nums子集非黄色部分一样
- 观察nums1的子集和nums黄色部分子集,可以发现,nums1子集每个list元素加入2即得到黄色部分子集;
- 因此得到迭代公式 subset([0,1]) + [2] = subset([0,1,2]);同理subset([0]) + [1] = subset([0,1])
- 迭代法代码如下:
"""
迭代方法:利用归纳思想,举例如下,{}用于提示读者注意迭代部分所在
nums=[1,2,3]
[]
[], {[1]} # 注意[1] 是 [] + [1] 得到
[], [1], {[2], [1,2]} # 注意[2],[1,2] 是 [] + [2] 和 [1] + [2]得到
[], [1], [2], [1,2], {[3], [1,3], [2,3], [1,2,3]}
"""
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[]]
for num in nums:
res += [r + [num] for r in res]
return res
- 递归/回溯法:思想是较长的子集是由较短的子集逐步添加元素构成的,具体如下
- 令nums=[0,1,2,3]
- 初始最短的子集为[ ],
- 接下来是包含1个元素的子集,为[0], [1], [2], [3]
- 接下来是包含2个元素的子集,以[0],[1]出发举例
- 对于[0],其包含2个元素子集为 [0,1], [0,2], [0,3];
- 对于[1],其包含2个元素子集为[1,2], [1,3];
- 可以发现,[0]和[1]都是在从后一个元素开始添加元素构成新的子集,这时就可以大概知道如何递归了,即在当前已有子集基础上,遍历添加后续所有元素,即可得到增加一个元素的新的子集;
- 值得一提的是,回溯体现在上述递归中还有遍历存在,如[0]递归得到[0,1],然后又递归得到[0,2],可视为[0,1]去掉[1]得到[0](故称为回溯)后添加[2]才得到的[0,2]
- 递归法代码如下
def subsets(self, nums: List[int]) -> List[List[int]]:
"""
回溯/递归方法:不断增加index及res_list
nums=[1,2,3,4]
[]
[1]...
[1,2],[1,3],[1,4]...
[1,2,3],[1,2,4]...
"""
res = []
if not nums:
return res
n = len(nums)
def helper(i, tmp):
res.append(tmp)
for j in range(i, n):
helper(j+1, r + [nums[j])
helper(0, [])
return res