513.找树左下角的值
本题要求找出该二叉树的 最底层 最左边 节点的值。
实际上是寻找深度最大的叶子结点中最左边的一个。
注意,满足条件的节点并不一定是左孩子。如下图所示,节点5虽然是节点3的右子孩子,但依然符合 最底层 最左边 这一条件。
首先定义一个全局变量,maxDepth,用于记录遍历到某叶子节点时,当前的最大深度,当我们到达新的叶子节点时,检查这个深度是否大于 maxDepth,如果大于,则更新结果。
需要注意的是,我们必须采用先左后右的顺序,否则,左右叶子节点否存在的情况下,会优先保存右叶子节点。
如下图所示,节点4是需要收集的最终结果。若我们采取先右后左的顺序。
当到达节点3时,若先遍历右子树到达节点5,此时由于5是叶子结点且深度更大,我们会收集节点5,并更新最大深度为3。
回到节点3,接着遍历左子树到达节点4,此时虽然4是叶子结点,但是深度并不大于3,因此不会记录节点4。
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
self.max_depth = float('-inf')
self.result = 0
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.max_depth = depth
self.result = node.val
return
# 如果不是叶子结点,继续向下递归
# 若调换左右遍历顺序,某些用例无法通过
if node.left:
depth += 1
self.traversal(node.left, depth)
depth -= 1
if node.right:
depth += 1
self.traversal(node.right, depth)
depth -= 1
本题使用层序遍历会比较好理解。
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
# 层序遍历
if not root:
return None
queue = deque([root])
left_most_value = 0
while queue:
level_size = len(queue)
# 维护每一层最左边节点的元素值
left_most_value = queue[0].val
for i in range(level_size):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return left_most_value
112.路径总和
只需要遍历到一条符合条件的路径,即可终止搜索。因此递归函数需要一个返回值。
在 113. 路径综合II中,则需要找出所有的路径,因此不需要返回值。
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 and count == 0:
return True
if not node.left and not node.right and count != 0:
return False
if node.left:
count -= node.left.val
if self.traversal(node.left, count):
return True
count += node.left.val
if node.right:
count -= node.right.val
if self.traversal(node.right, count):
return True
count += node.right.val
return False
113.路径总和II
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)
return self.result
def traversal(self, node, count):
if not node.left and not node.right and count == 0:
self.result.append(self.path[:])
return
if not node.left and not node.right and count != 0:
return
if node.left:
self.path.append(node.left.val)
count -= node.left.val
self.traversal(node.left, count)
count += node.left.val
self.path.pop()
if node.right:
self.path.append(node.right.val)
count -= node.right.val
self.traversal(node.right, count)
count += node.right.val
self.path.pop()
106.从中序与后序遍历序列构造二叉树
中序和后序都以特定的方式提供了树的信息:
- 中序遍历:每个节点的左子树和右子树分别位于该节点的左右侧
- 后序遍历:每个子树的最后一个元素是该子树的根节点
从根节点开始构造二叉树,首先定位到后序遍历的最后一个元素,其为此二叉树的根节点。在中序遍历中,此元素左边的元素构成左子树,右边的元素构成右子树。
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not inorder or not postorder:
return None
# 后序遍历的最后一个元素是根节点
root_val = postorder.pop()
# 创建一个根节点,下面对其左右指针赋值
root = TreeNode(root_val)
# 根节点在中序遍历中的位置
index = inorder.index(root_val)
# 接下来是对中序和后序的切片
# 首先来看中序:左中右
# 根节点在inorder中的索引为index,意味index左边的元素全部为左子树,inorder[:index]
# index右边的元素全部为右子树,inorder[index+1:]
# 其次来看后序:左右中
# 根节点在inorder中的索引为index,意味着左子树元素有index个,postorder[:index]
# 除开前index个和最后一个元素(已经pop)外,都为右子树元素,postorder[index:]
root.left = self.buildTree(inorder[:index], postorder[:index])
root.right = self.buildTree(inorder[index+1:], postorder[index:])
return root
105.从前序与中序遍历序列构造二叉树
- 前序遍历:每个子树的第一个元素是该子树的根节点
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if not preorder and not inorder:
return None
root_val = preorder[0]
root = TreeNode(root_val)
index = inorder.index(root_val)
# 接下来是对中序和前序的切片
# 首先来看中序:左中右
# 根节点在inorder中的索引为index,意味index左边的元素全部为左子树,inorder[:index]
# index右边的元素全部为右子树,inorder[index+1:]
# 其次来看前序:中左右
# 根节点在inorder中的索引为index,意味着左子树元素有index个,
# 由于preorder中的根节点并没被移除,从第二个开始的index个元素为左子树元素,preorder[1:index+1]
# 剩余都为右子树元素,preorder[index+1:]
root.left = self.buildTree(preorder[1 : index+1], inorder[ :index])
root.right = self.buildTree(preorder[index+1 :], inorder[index+1 :])
return root