最近刷二叉树的问题 用了很多递归 那么我就发现了一个问题 对于在递归中数组发生改变的函数 我们通常要进行一次回溯 而对于在递归中整数 也就是整型变量发生改变的函数中却不需要 我感觉是有所不同的 但是为了确定我心中的想法进行了一系列资料的查询 最终得出了想要的答案
问题来源
让我产生问题的分别是112. 路径总和 513. 找树左下角的值 以及257. 二叉树的所有路径
路径总和
class Solution:
def rest(self,node,summ):
if not node:
return
summ=summ-node.val
if summ==0 and (not node.left and not node.right):
return True
left=self.rest(node.left,summ)
if left==True:
return True
right=self.rest(node.right,summ)
if right==True:
return True
return False
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
t=self.rest(root,targetSum)
return t
这个是路径总和,变量summ每次都是同一个没有回溯
找树左下角的值
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
if not root.left and not root.right:
return root.val
self.result=[]
def depth(node,level):
if not node:
return
if len(self.result)==level:
self.result.append([])
self.result[level].append(node.val)
depth(node.left,level+1)
depth(node.right,level+1)
depth(root,0)
return self.result[-1][0]
这里的level也没有在做什么改变
二叉树的所有路径
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
def travel(node,result,Pass):
Pass.append(node.val)
if not node.left and not node.right:
sPass="->".join(map(str,Pass))
result.append(sPass)
if node.left:
travel(node.left,result,Pass)
Pass.pop()
if node.right:
travel(node.right,result,Pass)
Pass.pop()
return
if not root:
return
Pass=[]
result=[]
travel(root,result,Pass)
return(result)
先拆解一下这个函数吧,pass每次会储存节点,到达叶子节点后会加一个->变成spass 也就是一段路径 然后传到结果result当中,那么在这期间,每引用一次travel函数都会让pass增加一个数字,于是我们进行了一次回溯 确保在同一层中pass是相同的
解释和理解
在查阅资料后我发现了问题所在: 对于整型变量来说 比如调用t,每次调用t都只是在当前层中复制一个t的值然后传进去,每个递归调用都会创建独立的函数栈帧,栈帧里的remain_sum是局部变量,只在当前递归层级有效。左子树里的remain_sum修改,不会影响当前层,更不会影响传给右子树的remain_sum。
举个例子说明:
其实也就是说明了不可变类型的特点:就是修改时会创建一个新对象,而不是在原对象上修改,如同我们t=t-2一样,创建了一个新的t-2,然后把他赋给了一个变量t,而对于数组来说,我们修改数组(result.pop())就可以在原数组上发生,而不需要再重新赋值。