513.找树左下角的值
找最底层、最左边的值
- 迭代法找起来非常方便,可以按层序遍历,找到最后一层的第一个元素
- 递归法的话不是说一直找左节点就可以找到,因为要找到的是最后一层,所以要找到深度最大最左边的元素。在递归时先遍历左子树(前中后序都可实现),根据深度进行更改
迭代法
层序遍历的模板,稍微更改一下即可
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
from collections import deque
if not root:
return 0
queue = deque()
queue.append(root)
result = 0
while queue:
for i in range(len(queue)):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if i == 0:
result = node.val
return result
递归法
递归三部曲
- 参数为当前节点,当前的深度,根节点深度为0;返回值不需要,但是需要定义一个全局的结果值和深度值
- 终止条件:如果当前节点为空,返回(不需要,因为单层逻辑中已经判断是否为空了,不为空才可以遍历);如果当前节点为叶子节点,比较深度值,如果大,则更新结果值
- 单层逻辑:如果当前节点有左节点,则继续递归左节点,如果当前节点有右节点,则继续遍历右节点
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
self.result = 0
self.max_depth = float('-inf')
self.traversal(root, 0)
return self.result
def traversal(self, node, depth):
if not node.left and not node.right:
if depth > self.max_depth:
self.result = node.val
self.max_depth = depth
return
if node.left:
self.traversal(node.left, depth+1)
if node.right:
self.traversal(node.right, depth+1)
112. 路径总和
递归三部曲
- 参数为当前节点,计数器;返回值为是否存在
- 终止条件:如果当前节点为叶子节点,且计数器为0,则返回True;如果当前节点为叶子节点,计数器不为0,则返回False
- 单层逻辑:如果当前节点的左节点存在,则遍历左节点;如果当前节点的右节点存在,则遍历右节点。需要注意一点,遇见满足条件的才返回True,返回False的值先不考虑,最后才返回False
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
return self.traversal(root, targetSum-root.val)
def traversal(self, node, count):
if not node.left and not node.right:
return True if count == 0 else False
if node.left:
if self.traversal(node.left, count-node.left.val):
return True
if node.right:
if self.traversal(node.right, count-node.right.val):
return True
return False
精简版的代码是不要求判断当前节点是否存在才能迭代的,直接有判断为空则返回False
class Solution:
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
if not root:
return False
if not root.left and not root.right and sum == root.val:
return True
return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)
路径总和II
求出所有满足条件的路径,因为要遍历整棵树,找到所有路径,不需要返回值
以 Python 语言为例,记录路径时若直接执行 res.append(path) ,则是将此 path 对象加入了 res ;
后续 path 改变时, res 中的 path 对象也会随之改变,因此无法实现结果记录。正确做法为:list(path)或者path[:]
感想:Python的引用与拷贝还需要学习
下面为错误的,可以看看注释中出现的结果
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
self.result = []
self.path = []
if not root:
return self.result
self.path.append(root.val)
self.traversal(root, targetSum-root.val)
print(self.result)
# [[5], [5]]
return self.result
def traversal(self, node, count):
if not node.left and not node.right:
if count == 0:
self.result.append(self.path)
print(self.path, self.result)
# [5, 4, 11, 2] [[5, 4, 11, 2]]
# [5, 8, 4, 5] [[5, 8, 4, 5], [5, 8, 4, 5]]
else:
return
if node.left:
self.path.append(node.left.val)
self.traversal(node.left, count-node.left.val)
self.path.pop()
if node.right:
self.path.append(node.right.val)
self.traversal(node.right, count-node.right.val)
self.path.pop()
正确的做法
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
self.path = []
self.result = []
if not root:
return self.result
self.path.append(root.val)
self.traversal(root, targetSum-root.val)
return self.result
def traversal(self, node, count):
if not node.left and not node.right:
if count == 0:
self.result.append(self.path[:])
else:
return
if node.left:
self.path.append(node.left.val)
self.traversal(node.left, count-node.left.val)
self.path.pop()
if node.right:
self.path.append(node.right.val)
self.traversal(node.right, count-node.right.val)
self.path.pop()
106.从中序与后序遍历序列构造二叉树
中序遍历和后序遍历构建二叉树
- 如果后序遍历无元素,返回空
- 后序遍历的最后一个元素为根节点
- 根据根节点分割中序遍历,分为中序遍历的左子树和右子树
- 根据中序遍历分割的左右子树的长度,分割得到后序遍历的左右子树
- 根据分割的中序和后序的左右子树,再去递归
- 返回根节点
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)
sep_index = inorder.index(root_val)
inorder_left = inorder[:sep_index]
inorder_right = inorder[sep_index+1:]
postorder_left = postorder[:len(inorder_left)]
postorder_right = postorder[len(inorder_left):-1]
root.left = self.buildTree(inorder_left, postorder_left)
root.right = self.buildTree(inorder_right, postorder_right)
return root