- 迭代法 用层序遍历(可以调整为只添加第一个节点)
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
if not root:
return
que = [root]
res = []
while que:
n = len(que)
tmp = []
while n:
node = que.pop(0)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
tmp.append(node.val)
n -= 1
res.append(tmp)
return res[-1][0]
思路:
与遍历顺序无关
利用和targetSum的差值传参
递归三部:
终止条件:count==0; none值
if not node.left and not node.right:
return count == 0
遍历顺序:
其实没有对中节点的处理过程,所以相当于前中后遍历都可以
递归过程中,如果遇到返回值为true的,一级级返回上去
分别进行左右遍历
回溯:把节点值加回count 即回退
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
def recursion(root, targetRes):
if not root:
return False
if not root.left and not root.right:
return targetRes == 0
if root.left and recursion(root.left, targetRes-root.left.val):
return True
if root.right and recursion(root.right, targetRes-root.right.val):
return True
return False
# initial val
return recursion(root, targetSum-root.val)
因为要遍历整个树,找到所有路径,所以递归函数不要返回值!
领悟一下遍历后用数组存储的过程
用append和pop来实现回溯
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
if not root:
return []
res = []
def recursion(root, targetRes, tmp):
if not root:
return
if not root.left and not root.right:
if targetRes == 0:
res.append(tmp[::])
return
if root.left:
tmp.append(root.left.val)
recursion(root.left, targetRes-root.left.val, tmp)
tmp.pop()
if root.right:
tmp.append(root.right.val)
recursion(root.right, targetRes-root.right.val, tmp)
tmp.pop()
return
recursion(root, targetSum-root.val, [root.val])
return res
递归在树中的应用
先搞懂回溯的过程再去看精简版的代码
理解回溯的逻辑
如果遇到不符合条件的,返回上一节点
要理解如何返回上一节点,即在结果中删去该节点
构造二叉树
中序:左中右 后序:左右中
【看视频理解思路】 6步
- 判断postorder为空
- postorder最后一个元素为中间节点
- 寻找inorder数组中切割点 index
- 切inorder 用中间节点
- 切postorder 用的是切好的inorder的左右区间长度
- 递归处理 左区间 右区间
注:先理解构建过程时要一步步切分左右区间
后序:最后一个节点一定是root,从而区分左右区间;划分好区间后,在后序中对应的最后一位就是中间节点
递归处理左区间右区间
优化:如果len==1,说明仅有一个节点
先得到的都是left,用后序的点在中序中定位,确定是否有左右节点
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
if not postorder:
return
# 第二步: 后序遍历的最后一个就是当前的中间节点
root_val = postorder[-1]
root = TreeNode(root_val)
# 第三步: 找切割点.
root_index = inorder.index(root_val)
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
left_inorder = inorder[:root_index]
right_inorder = inorder[root_index + 1:]
# 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
# ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
left_postorder = postorder[:len(left_inorder)]
right_postorder = postorder[len(left_inorder): len(postorder) - 1]
# 第六步: 递归
root.left = self.buildTree(left_inorder, left_postorder)
root.right = self.buildTree(right_inorder, right_postorder)
# 第七步: 返回答案
return root