算法刷题-二叉树5
404. 左叶子之和
给定二叉树的根节点 root
,返回所有左叶子之和。
思路
这道题是求二叉树中所有左叶子节点的值的和。使用递归的方法来解决。首先判断根节点是否为空,如果是,则直接返回0。然后定义一个变量sum来记录左叶子节点的值的和,初始值为0。接着判断根节点的左子节点是否存在,并且左子节点的左子节点和右子节点都不存在,如果满足条件,则将左子节点的值加到sum中。然后递归调用sumOfLeftLeaves函数来计算左子树中左叶子节点的值的和,并将结果加到sum中。再递归调用sumOfLeftLeaves函数来计算右子树中左叶子节点的值的和,并将结果加到sum中。最后返回sum即可。
代码
from typing import Optional
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
sum = 0
if root.left and root.left.left is None and root.left.right is None:
sum += root.left.val
return sum + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
513. 找树左下角的值
给定一个二叉树的 根节点 root
,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
思路
这道题是要找出二叉树中最底层最左边的节点的值。使用广度优先搜索(BFS)的方法来解决。
- 首先创建一个队列queue,并将根节点root加入到队列中。同时初始化一个变量res来记录最底层最左边节点的值,初始值为根节点的值root.val。
- 然后进行循环,直到队列为空。在每一轮循环中,先获取当前队列的大小sz,表示当前层的节点个数。然后通过循环从队列中取出sz个节点进行处理。在处理节点的过程中,如果当前节点是当前层的第一个节点
i==0
,则更新res为当前节点的值。 - 接着判断当前节点是否有左子节点和右子节点,如果有,则将它们加入到队列中。
- 最后返回res即可。
代码
# Definition for a binary tree node.
import collections
from typing import Optional
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
queue = collections.deque([root])
res = root.val
while queue:
sz = len(queue)
for i in range(sz):
node = queue.popleft()
if i == 0:
res = node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return res
112. 路径总和
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
思路
这道题是判断二叉树中是否存在一条从根节点到叶子节点的路径,使得路径上所有节点值的和等于给定的目标和targetSum。使用广度优先搜索(BFS)的方法来解决。
- 首先判断根节点是否为空,如果为空,则直接返回False。然后创建两个队列node_queue和val_queue,分别用来存储节点和节点值。将根节点root和根节点的值root.val分别加入到队列中。
- 接下来进行循环,直到队列为空。在每一轮循环中,从队列中取出一个节点node和对应的节点值val。判断当前节点是否为叶子节点(即没有左子节点和右子节点),如果是,则判断路径上的节点值之和是否等于目标和targetSum,如果相等,则返回True。如果当前节点有左子节点,则将左子节点和路径上节点值之和加入到队列中。如果当前节点有右子节点,则将右子节点和路径上节点值之和加入到队列中。
- 最后如果循环结束仍未找到满足条件的路径,则返回False。
代码
# Definition for a binary tree node.
import collections
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
from typing import Optional
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
node_queue = collections.deque([root])
val_queue = collections.deque([root.val])
while node_queue:
node = node_queue.popleft()
val = val_queue.popleft()
if not node.left and not node.right: # 叶子
if targetSum==val:
return True
if node.left:
node_queue.append(node.left)
val_queue.append(node.left.val+val)
if node.right:
node_queue.append(node.right)
val_queue.append(node.right.val+val)
return False
106. 从中序与后序遍历序列构造二叉树
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
思路
中序遍历:左根右
后序遍历:左右根
因此postorder的最后一个就是根节点
深度优先搜索(DFS)
- 首先定义一个辅助函数dfs,接收两个参数l和r,表示当前子树的中序遍历的起始位置和结束位置。如果l大于r,说明当前子树为空,返回None。
- 然后从后序遍历的结果中取出最后一个元素作为当前子树的根节点的值val,并创建一个节点root。接着通过字典mp来获取val在中序遍历结果中的索引idx。根据idx将中序遍历结果分为左子树和右子树的部分,分别递归调用dfs函数构建左子树和右子树,并将它们分别赋值给root的左子节点和右子节点。
- 最后返回root即可。在主函数buildTree中,首先创建一个空字典mp,用来存储中序遍历结果中每个元素的索引。然后通过循环遍历中序遍历结果,将每个元素及其索引存入字典中。接着调用dfs函数,传入中序遍历结果的起始位置0和结束位置len(inorder)-1,返回构建好的二叉树的根节点。
代码
# Definition for a binary tree node.
from typing import List, Optional
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
def dfs(l, r) -> TreeNode:
if l > r:
return None
val = postorder.pop()
root = TreeNode(val)
idx = mp[val]
root.right = dfs(idx + 1, r)
root.left = dfs(l, idx - 1)
return root
mp = {}
for i in range(len(inorder)):
mp[inorder[i]] = i
return dfs(0, len(inorder) - 1)
654. 最大二叉树
给定一个不重复的整数数组 nums
。 最大二叉树 可以用下面的算法从 nums
递归地构建:
- 创建一个根节点,其值为
nums
中的最大值。 - 递归地在最大值 左边 的 子数组前缀上 构建左子树。
- 递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums
构建的 最大二叉树 。
思路
使用深度优先搜索(DFS)
- 首先定义一个辅助函数dfs,接收两个参数l和r,表示当前子数组的起始位置和结束位置。如果l大于r,说明当前子数组为空,返回None。
- 然后在当前子数组中找到最大值mx及其索引idx。遍历子数组,如果找到比当前最大值mx更大的元素,则更新最大值mx和索引idx。创建一个节点root,值为最大值mx。然后根据idx将子数组分为左子数组和右子数组,分别递归调用dfs函数构建左子树和右子树,并将它们分别赋值给root的左子节点和右子节点。
- 最后返回root即可。在主函数constructMaximumBinaryTree中,调用dfs函数,传入数组的起始位置0和结束位置len(nums)-1,返回构建好的最大二叉树的根节点。
代码
# Definition for a binary tree node.
from typing import Optional, List
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
def dfs(l, r) -> TreeNode:
if l > r:
return None
mx = nums[l]
idx = l
for i in range(l, r + 1):
if nums[i] > mx:
mx = nums[i]
idx = i
root = TreeNode(mx)
root.left = dfs(l, idx - 1)
root.right = dfs(idx + 1, r)
return root
return dfs(0, len(nums) - 1)