力扣 子集
宏观:递、归(回溯)+收集结果res
微观:怎么一层一层往下递,怎么往上归(回溯)
先写宏观:
递归三部曲:
1 def 函数,确定传参,传的参数就是原始的nums
2 一个path存每条路的小答案,res收集最后回溯回来的总结果
3 一个实现回溯的函数
def subsets(self,nums):
result = []
path = []
self.backtracking() #不知道回溯的传参是啥,先空着,,等下面回溯函数写好了再回头写
return result
宏观写好了,宏观上就是,先递后归+收集path小结果和res总结果
现在写微观,微观就是,写递归函数,自从nums原始数组开始传递的时候,这个传递的逻辑是什么?怎怎么递,什么时候归(回溯)
递归伴随着回溯
递归三部曲:
1 确定传参和返回值,把要传的,用到的参数和返回值都放进去
2 终止条件,什么时候停止递(什么时候不能再往下了)
3 遍历的逻辑是什么?怎么遍历
设置函数
def backtracking(self,nums,startindex,path,res):#确定传参和返回值
result.append(path[:])
注意!#收集path,放在终止添加的上面,否则会漏掉自己
如果不对当前的路径进行保存,那么在回溯(即撤销选择)之后,当前路径的信息就会丢失,因为它会被新的选择覆盖。
if startindex >= len(nums): #终止条件
return
for i in range(startindex,len(nums)):
path.append(nums[i])
# 怎么确定什么时候开始回溯?就是什么时候写self.backtracking的函数?
就是看,什么时候开始往下一层遍历;刚刚是根据索引把数字取出来放在path了,接下来就是往下一层递了。所以开始写递归函数
因为整体,宏观或者微观的逻辑都是一样的,所以开始套娃
self.backtracking(nums,i+1,path,res)
path.pop() #递归函数写好了,就开始回溯,尝试别的路
到回溯,所有就写完了
回头补一下
self.backtracking() #不知道回溯的传参是啥,先空着,,等下面回溯函数写好了再回头写
就是,nums,startindex=0,path,result
!!!这样写不对,要传具体的参数就一起传递,保持一致,不然报错!
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
result = []
path = []
self.backtracking(nums,startindex=0,path=path,result=result)#这里不能单独写startindex=0,要写就把后面的一起写,保持一致
return result
def backtracking(self,nums,startindex,path,result):
result.append(path[:])
if startindex > len(nums):
return
for i in range(startindex,len(nums)):
path.append(nums[i])
self.backtracking(nums,i+1,path,result)
path.pop()
代码
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
result = []
path = []
self.backtracking(nums,startindex=0,path=path,result=result)#这里不能单独写startindex=0,要写就把后面的一起写,保持一致
return result
def backtracking(self,nums,startindex,path,result):
result.append(path[:])
if startindex > len(nums):
return
for i in range(startindex,len(nums)):
path.append(nums[i])
self.backtracking(nums,i+1,path,result)
path.pop()