513. 找树左下角的值
题目:给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例 1:
输入: root = [2,1,3]
输出: 1
示例 2:
****
输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7
解题思路1: 层序遍历
- 时间复杂度:O(n),其中 n 是二叉树的节点数目。
- 空间复杂度:O(n),如果二叉树是满完全二叉树,那么队列 q 最多保存 ⌈n/2⌉个节点。
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
if not root:
return root
queue = [root]
result = -1 # 记录最底层左边的节点值
while queue:
size = len(queue)
for i in range(size):
node = queue.pop(0)
if i == 0:
result = node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
# 从右到左的层次遍历,最后一个节点就是最底层左边的节点
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
if not root:
return root
queue = [root]
result = -1 # 记录最底层左边的节点值
while queue:
size = len(queue)
for i in range(size):
node = queue.pop(0)
result = node.val
# 先右再左
if node.right:
queue.append(node.right)
if node.left:
queue.append(node.left)
return result
解题思路2
递归时先遍历左再右,如果左边达到最大深度了就更新结果。
- 时间复杂度:O(n),其中 n 是二叉树的节点数目。需要遍历 n 个节点。
- 空间复杂度:O(n),递归栈需要占用 O(n) 的空间。
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
# if not root:
# return -1
self.maxDepth = -1
self.result = 0
self.traverse(root, depth=1) # check depth
return self.result
def traverse(self, root, depth=0):
# 终止条件
if not root.left and not root.right:
if depth > self.maxDepth:
self.maxDepth = depth
self.result = root.val
# 先遍历左再右,这样优先更新最大深度的左节点
if root.left:
self.traverse(root.left, depth+1)
if root.right:
self.traverse(root.right, depth+1)
总结
最简单的是层次遍历,记录最后一层第一个节点值即可;或者从右往左层次遍历,记录最后一个节点;dfs时候需要记录depth,然后由于对中间节点没有操作,只需要保证先左孩子再右孩子即可。
112. 路径总和
题目:给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
示例 1:
输入: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出: true
解释: 等于目标和的根节点到叶节点路径如上图所示。
示例 2:
输入: root = [1,2,3], targetSum = 5
输出: false
解释: 树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。
解题思路
- 时间复杂度:O(n)
- 空间复杂度:O(n)
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
# 叶子节点:
if not root.left and not root.right:
return root.val == targetSum
return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum-root.val)
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
return self.traverse(root, root.val, targetSum)
def traverse(self, root, current_sum, targetSum) -> bool:
# 检查叶子节点
if not root.left and not root.right:
return current_sum == targetSum
found_path = False
if root.left:
found_path = self.traverse(root.left, current_sum + root.left.val, targetSum)
if root.right:
found_path = found_path or self.traverse(root.right, current_sum + root.right.val, targetSum)
return found_path
106. 从中序与后序遍历序列构造二叉树
题目:给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入: inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出: [3,9,20,null,null,15,7]
解题思路
- 时间复杂度:O(n),其中 n 是树中的节点个数。
- 空间复杂度:O(n),需要使用 O(n) 的空间存储哈希表,以及 O(h)(其中 h 是树的高度logn)的空间表示递归时栈空间。这里 h<n,所以总空间复杂度为 O(n)
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
self.val2idx = {}
for i in range(len(inorder)):
self.val2idx[inorder[i]] = i
return self.build(inorder, 0, len(inorder)-1, postorder,0, len(postorder)-1)
def build(self, inorder, in_start, in_end, postorder, post_start, post_end):
if in_start > in_end:
return None
root_val = postorder[post_end]
root_idx = self.val2idx[root_val]
left_size = root_idx - in_start
root = TreeNode(val=root_val)
root.left = self.build(inorder,in_start, root_idx -1,
postorder,post_start, post_start +left_size-1)
root.right = self.build(inorder,root_idx+1, in_end,
postorder, post_start+left_size, post_end-1)
return root