513.找树左下角的值
注意树左下角的值指的是二叉树最底层最左边节点的值。所以使用层次遍历的方法比较简单,遍历每一层时都将该层的最左边节点的值保存下来,当遍历结束后将这个值返回即可。
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
if not root:
return None
queue = deque([root])
while queue:
for i in range(len(queue)):
node = queue.popleft()
if i == 0:
result = node.val # 记录当前层最左边节点的值
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
112.路径总和
递归法:
1.递归函数参数及返回值:当前遍历节点以及一个计数器,返回值为bool型变量。
def traversal(self, cur, count):
2.递归终止条件:采用递减的方式,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。如果最后count == 0,同时到了叶子节点的话,说明找到了目标和。如果遍历到了叶子节点,count不为0,就是没找到。
if not cur.left and not cur.right:
return True if result == 0 else False
3.单层递归逻辑:因为终止条件是判断叶子节点,所以递归的过程中不让空节点进入递归。递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。
if cur.left:
result -= cur.left.val
if self.traversal(cur.left, result):
return True
result += cur.left.val
if cur.right:
result -= cur.right.val
if self.traversal(cur.right, result):
return True
result += cur.right.val
return False
递归法完整代码:
class Solution:
def traversal(self, cur, result):
if not cur.left and not cur.right:
return True if result == 0 else False
if cur.left:
result -= cur.left.val
if self.traversal(cur.left, result):
return True
result += cur.left.val # 回溯,将减去的值加回去
if cur.right:
result -= cur.right.val
if self.traversal(cur.right, result):
return True
result += cur.right.val
return False
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
return self.traversal(root, targetSum - root.val)
本题也可采用迭代法,使用层次遍历来求解:
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
queue = deque([root])
path = deque([root.val]) # 用另一个队列来存储路径值,便于回退
count = 0
while queue:
for _ in range(len(queue)):
node = queue.popleft()
count = path.popleft()
if not node.left and not node.right:
if count == targetSum:
return True
if node.left:
queue.append(node.left)
path.append(count + node.left.val)
if node.right:
queue.append(node.right)
path.append(count + node.right.val)
return False
113.路经总和Ⅱ
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
result = []
path = []
self.traversal(root, targetSum, path, result)
return result
def traversal(self,node, count, path, result):
if not node:
return
path.append(node.val)
count -= node.val
if not node.left and not node.right and count == 0:
result.append(list(path))
self.traversal(node.left, count, path, result)
self.traversal(node.right, count, path, result)
path.pop()
106.从中序与后序遍历序列构造二叉树
原理:以后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
步骤:
1.若后序数组为0,返回空节点
2.后序数组的最后一个元素作为节点元素
3.在中序数组中寻找2.得到的节点元素作为切割点
4.切中序数组
5.切后序数组
6.递归处理左右区间
简而言之就是通过后序数组和中序数组来确定左右子树,进而切割得到左右子树的后序和中序数组,然后进行递归就能求出整个树。
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not postorder: # 树为空则返回null
return None
root_val = postorder[-1] # 后序数组的最后一个值为根节点的值
root = TreeNode(root_val) # 创建根节点
index = inorder.index(root_val) # 查找根节点在中序数组中的位置
left_inorder = inorder[:index] # 切割中序数组,构建左中序数组,即为左子树
right_inorder = inorder[index+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 # 返回结果
105.从前序与中序遍历序列构造二叉树
本题思路与前一题基本一致,只需要将对后序数组的处理改为前序数组对应的处理即可。
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if not preorder:
return None
root_val = preorder[0]
root = TreeNode(root_val)
index = inorder.index(root_val)
left_inorder = inorder[:index]
right_inorder = inorder[index+1:]
# 注意中序数组的长度和前序数组一定是一样的
left_preorder = preorder[1:1+len(left_inorder)]
right_preorder = preorder[1+len(left_inorder):]
root.left = self.buildTree(left_preorder, left_inorder)
root.right = self.buildTree(right_preorder, right_inorder)
return root