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 的根节点到叶子节点的路径。示例 3:
输入:root = [], targetSum = 0 输出:false 解释:由于树是空的,所以不存在根节点到叶子节点的路径。提示:
- 树中节点的数目在范围
[0, 5000]
内-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def hasPathSum(self, root, targetSum):
"""
:type root: TreeNode
:type targetSum: int
:rtype: bool
注释之前: time: O(n) space: O(n)
注释之后: time: O(n) space: O(h). h 是树的高度。
"""
if root is None:
return False
# 栈用于深度优先遍历
stack = [(root, root.val)]
res = [] # 存储所有路径上所有节点值相加之和
while stack:
node, sum_val = stack.pop()
# 如果是叶子节点,则得到最后的总和值
if not node.left and not node.right:
# res.append(sum_val)
if sum_val == targetSum:
return True
# 如果左子节点存在,更新总和值并入栈
if node.left:
stack.append((node.left, sum_val + node.left.val))
# 如果右子节点存在,更新总和值并入栈
if node.right:
stack.append((node.right, sum_val + node.right.val))
# return targetSum in res
return False
113. 路径总和 II
给你二叉树的根节点
root
和一个整数目标和targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 输出:[[5,4,11,2],[5,8,4,5]]示例 2:
输入:root = [1,2,3], targetSum = 5 输出:[]示例 3:
输入:root = [1,2], targetSum = 0 输出:[]提示:
- 树中节点总数在范围
[0, 5000]
内-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def pathSum(self, root, targetSum):
"""
:type root: TreeNode
:type targetSum: int
:rtype: List[List[int]]
time: O(n*log(n))
space: O(n^2)
"""
if not root:
return []
stack = [(root, [root.val])]
res = [] # 存储最后所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
while stack:
node, path = stack.pop()
# 如果是叶子节点,判断路径总和等于给定目标
if not node.left and not node.right:
if sum(path) == targetSum:
res.append(path)
# 如果有左叶子节点,更新路径
if node.left:
stack.append((node.left, path + [node.left.val]))
# 如果有右叶子节点,更新路径
if node.right:
stack.append((node.right, path + [node.right.val]))
return res
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]示例 2:
输入:inorder = [-1], postorder = [-1] 输出:[-1]提示:
1 <= inorder.length <= 3000
postorder.length == inorder.length
-3000 <= inorder[i], postorder[i] <= 3000
inorder
和postorder
都由 不同 的值组成postorder
中每一个值都在inorder
中inorder
保证是树的中序遍历postorder
保证是树的后序遍历
先切中序数组,再切前/后序数组
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
time: O(n^2)
space: O(n)
"""
# 特殊情况讨论: 树为空. (递归终止条件)
if not inorder or not postorder:
return None
# 后序遍历的最后一个元素是根节点
root_val = postorder.pop()
root = TreeNode(root_val)
# 在中序遍历中找到根节点的位置,这样我们就知道左右子树的节点数了
idx = inorder.index(root_val)
# 计算左子树的大小
left_size = idx
# 构建左子树和右子树
# 注意我们如何切分postorder
root.left = self.buildTree(inorder[:idx], postorder[:left_size])
root.right = self.buildTree(inorder[idx+1:], postorder[left_size:])
return root
此函数的核心思路是:
- 从后序遍历中取出最后一个元素,即为当前的根。
- 在中序遍历中找到该元素的位置,将数组分为两部分,一部分是左子树的所有元素,另一部分是右子树的所有元素。
- 递归地对左子树和右子树进行上述操作。
105. 从前序与中序遍历序列构造二叉树
给定两个整数数组
preorder
和inorder
,其中preorder
是二叉树的先序遍历,inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]示例 2:
输入: preorder = [-1], inorder = [-1] 输出: [-1]提示:
1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder
和inorder
均 无重复 元素inorder
均出现在preorder
preorder
保证 为二叉树的前序遍历序列inorder
保证 为二叉树的中序遍历序列
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
time: O(N^2)
space: O(N)
"""
if not preorder or not inorder:
return None
# 前序遍历的第一个元素是根节点
root_val = preorder.pop(0)
root = TreeNode(root_val)
# 在中序遍历中找到根节点的位置,这样我们就知道左右子树的节点数了
idx = inorder.index(root_val)
# 计算左子树的大小
left_size = idx
# 构建左子树和右子树
# 注意我们如何切分preorder
root.left = self.buildTree(preorder[:left_size], inorder[:idx])
root.right = self.buildTree(preorder[left_size:], inorder[idx+1:])
return root