思路:
回溯的思路就是我们遍历每一个元素
这个元素选,或者不选
选那么下一次还可以选择这个元素或者不选这个元素 dfs(i, left - candidate[i])
不选这个元素就只能下一次只能选择下一个元素 dfs(i + 1, left)
我一直认为回溯学好的办法就是图画出来,清晰的知道为什么算法可以把每一种情况都跑出来,并且不会陷入死循环
Tip: csdn连图像都不能旋转我真是醉了
代码
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
ans = []
path = []
candidates.sort()
def dfs(i, left):
if left == 0:
ans.append(path.copy())
return
if i == len(candidates) or left < candidates[i]:
return
## 不选
dfs(i + 1, left)
## 选
path.append(candidates[i])
print(path)
dfs(i, left - candidates[i])
path.pop()
dfs(0, target)
return ans
几个问题
1、首先是为什么能够跑出答案:
因为回溯直接把所有情况都枚举出来,知道撞到南墙我们才回去
2、path 作为循环不变量, 他的含义一直是我们组合已经选择的数字
首先path 从图上直观的看就是我们从根节点,到某个节点的路径上的所有节点的列表
3、 path.pop() 到底是什么,回溯的恢复现场,到底是什么意思
path.pop()就是为了让path作为循环不变量,他的含义一直是我们组合已经选择的数字
从图上来看,path.pop() 执行的时候就是当沿着左孩子径我们走到方框时,我们需要切换到右孩子,这时候我们的左孩子就不在我们的路径上了,所以我们要pop()出来左孩子
我是一个学习算法的初学者,希望把一切复杂的东西用最直观的方式解释出来,希望大家能指出我的不足,共同进步