题目链接:513. 找树左下角的值 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——513.找树左下角的值
视频讲解:怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值_哔哩哔哩_bilibili
"""
层序遍历,返回最后一组数组的第1个元素
"""
# 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 findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
# 定义一个队列
que = collections.deque()
res = []
# 如果根节点不为空则加入队列
if root is not None:
que.append(root)
# 遍历终止条件为队列中没有元素了
while que:
# 记录当前层节点数
size = len(que)
# 定义一个数组放当前层元素
vator = []
for i in range(size):
# 从队列中弹出当前节点
cur = que.popleft()
# 将当前节点值放到当前层的结果中
vator.append(cur.val)
# 将节点左右子节点加入队列
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
# 将当前层元素加入结果
res.append(vator)
return res[-1][0]
思路:找深度最大的叶子节点
"""
递归,找左右子节点,不用考虑中,因此哪种遍历顺序都可以
"""
# 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:
# 1. 确定递归函数的参数和返回值
def traversal(self, node, depth):
# 2. 确定终止条件,左右子节点都为空
if not node.left and not node.right:
# 遇到叶子节点深度大于我当前最大深度,更新最大深度,并记录当前节点数值
if depth > self.max_depth:
self.max_depth = depth
self.result = node.val
# 3. 单层递归
# 左
if node.left:
depth += 1
self.traversal(node.left, depth) # 回溯
depth -= 1
# 右
if node.right:
depth += 1
self.traversal(node.right, depth)
depth -= 1
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
self.max_depth = float('-inf')
self.result = None
self.traversal(root, 0)
return self.result
题目链接:112. 路径总和 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——112. 路径总和
视频讲解:拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和_哔哩哔哩_bilibili
"""
错误代码!
递归,没有中的逻辑,那种遍历顺序都可以
"""
# 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:
# 1. 确定递归函数的参数和返回值,count为目标值
def traversal(self, node, count):
# 2. 确定终止条件
# 为叶子节点且count--后为0
if not node.left and not node.right and count == 0:
return True
# 为叶子节点但count--后不为0
if not node.left and not node.right and count != 0:
return False
# 3. 确定单层递归的逻辑
# 判断左节点不为空
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
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
# 返回值出错,目标值要减去根节点值
return self.traversal(root, targetSum)
"""
正确代码
递归,没有中的逻辑,那种遍历顺序都可以
"""
# 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:
# 1. 确定递归函数的参数和返回值,count为目标值
def traversal(self, node, count):
# 2. 确定终止条件
# 为叶子节点且count--后为0
if not node.left and not node.right and count == 0:
return True
# 为叶子节点但count--后不为0
if not node.left and not node.right and count != 0:
return False
# 3. 确定单层递归的逻辑
# 判断左节点不为空
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
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
return self.traversal(root, targetSum - root.val)
题目链接:113. 路径总和 II - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——113. 路径总和ii
# 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 __init__(self):
self.result = []
self.path = []
# 1. 确定递归函数的参数和返回值
def traversal(self, node, count):
# 2. 确定终止条件
# 为叶子节点且总和为目标值,将其加入path种
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
# 3. 确定单层递归逻辑
# 左
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() # 回溯
return
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
if not root:
return self.result
# 根节点放入路径
self.path.append(root.val)
self.traversal(root, targetSum - root.val)
return self.result
题目链接:106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——106.从中序与后序遍历序列构造二叉树
视频讲解:坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树_哔哩哔哩_bilibili
思路:
① 后序数组为0,则空节点;
② 后序数组最后一个元素为根节点;
③ 根节点作为中序数组的切割点,分成左右区间;
④ 切割中序数组;
⑤ 切割后序数组;
⑥ 递归处理左右区间。
# 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 buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
# 第1步,后序数组为0,则空节点
if len(postorder) == 0:
return None
# 第2步,后序数组最后一个元素为根节点
root_val = postorder[-1]
root = TreeNode(root_val)
if len(postorder) == 1:
return root
# 第3步,根节点作为中序数组的切割点,分成左右区间
index = 0
for index in range(len(inorder)):
if inorder[index] == root_val:
break
# 第4步,切割中序数组
inorder_left = inorder[:index]
inorder_right = inorder[index + 1:]
# 第5步,切割后序数组,根据中序数组左右区间长度
postorder_left = postorder[:len(inorder_left)]
postorder_right = postorder[len(inorder_left):len(postorder) - 1]
# 第6步,递归处理左右区间
root.left = self.buildTree(inorder_left, postorder_left)
root.right = self.buildTree(inorder_right, postorder_right)
return root
题目链接:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
思路:
① 前序数组为0,则空节点;
② 前序数组第一个元素为根节点;
③ 根节点作为中序数组的切割点,分成左右区间;
④ 切割中序数组;
⑤ 切割前序数组;
⑥ 递归处理左右区间。
# 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
# 第1步,前序数组为0,则空节点
if len(preorder) == 0:
return None
# 第2步,前序数组第一个元素为根节点
root_val = preorder[0]
root = TreeNode(root_val)
# 第3步,根节点作为中序数组的切割点,分成左右区间
index = 0
for index in range(len(preorder)):
if inorder[index] == root_val:
break
# 第4步,切割中序数组
inorder_left = inorder[:index]
inorder_right = inorder[index + 1:]
# 第5步,根据中序数组左右区间长度,切割前序数组
preorder_left = preorder[1:1 + len(inorder_left)]
preorder_right = preorder[1 + len(inorder_left):]
# 第6步,递归处理左右区间
root.left = self.buildTree(preorder_left, inorder_left)
root.right = self.buildTree(preorder_right, inorder_right)
return root