一、110.平衡二叉树
题目链接:110. 平衡二叉树 - 力扣(LeetCode)
文章讲解:110.平衡二叉树 | 代码随想录 (programmercarl.com)
视频讲解:后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树_哔哩哔哩_bilibiliCarl说:再一次涉及到,什么是高度,什么是深度,可以巩固一下。
"""
错误代码,理解错误,不是比较最小深度和最大深度差是否小于1,而是比较左右子树高度差是否不超过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 getdepth(self, node):
if not node:
return 0
leftdepth = self.getdepth(node.left)
rightdepth = self.getdepth(node.right)
depth = 1 + max(leftdepth, rightdepth)
return depth
# 获取最小深度
def getheight(self, node):
if not node:
return 0
leftheight = self.getheight(node.left)
rightheight = self.getheight(node.right)
# 左子树为空,右子树不为空,则高度为右子树高度+1
if node.left == None and node.right != None:
return 1 + rightheight
# 左子树不为空,右子树为空,则高度为左子树高度+1
if node.left != None and node.right == None:
return 1 + leftheight
# 左右子树均不为空,则高度为左右子树高度+1
result = 1 + min(leftheight, rightheight)
return result
# 判断是否为平衡树
def isBalanced(self, root: Optional[TreeNode]) -> bool:
error = self.getdepth(root) - self.getheight(root)
if error <= 1:
return True
else:
return False
"""
正确代码
"""
# 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 getheigh(self, node):
# 2. 确定终止条件
if not node:
return 0
# 3. 确定单层递归的逻辑,后序遍历
leftheight = self.getheigh(node.left) # 左
# 左子树不符合平衡二叉树条件
if leftheight == -1:
return -1
rightheight = self.getheigh(node.right) # 右
# 右子树不符合平衡二叉树条件
if rightheight == -1:
return -1
# 左右子树都符合平衡二叉树,判断高度差
if abs(leftheight - rightheight) > 1: # 中
return -1
else:
return 1 + max(leftheight, rightheight)
def isBalanced(self, root: Optional[TreeNode]) -> bool:
if self.getheigh(root) != -1:
return True
else:
return False
二、257. 二叉树的所有路径
题目链接:257. 二叉树的所有路径 - 力扣(LeetCode)
文章讲解:257. 二叉树的所有路径 | 代码随想录 (programmercarl.com)
视频讲解:递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径_哔哩哔哩_bilibiliCarl说:这是大家第一次接触到回溯的过程, 我在视频里重点讲解了 本题为什么要有回溯,已经回溯的过程。 如果对回溯 似懂非懂,没关系, 可以先有个印象。
遍历顺序:前序遍历,因为需要父节点指向子节点,并将路径输出。
# 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, path, result):
# 中,把中值加入path中
path.append(node.val)
# 2. 确定终止条件,node左右子节点都为空
if not node.left and not node.right:
path_res = '->'.join(map(str, path))
result.append(path_res)
return
# 左
if node.left:
self.traversal(node.left, path, result)
path.pop() # 回溯
# 右
if node.right:
self.traversal(node.right, path, result)
path.pop() # 回溯
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
# 1. 确定递归函数的参数和返回值
result = []
path = []
# 2. 确定终止条件
if not root:
return result
# 3. 确定单层递归的逻辑
self.traversal(root, path, result)
return result
三、404.左叶子之和
题目链接:404. 左叶子之和 - 力扣(LeetCode)
文章讲解:404.左叶子之和 | 代码随想录 (programmercarl.com)
视频讲解:二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和_哔哩哔哩_bilibiliCarl说:其实本题有点文字游戏,搞清楚什么是左叶子,剩下的就是二叉树的基本操作。
思路:通过父节点判断子节点是否为想要收集的元素,父节点左子节点不为空,且左子节点左右都为空则为我们要操作的元素。
遍历顺序:后序遍历,需要一层一层向上返回。
# 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:
# 2. 确定终止条件
# 根节点为空,返回0
if not root:
return 0
# 遍历到叶子节点时没有左右子节点,返回0
if not root.left and not root.right:
return 0
# 3. 确定单层递归的逻辑,后序遍历
# 左
left_num = self.sumOfLeftLeaves(root.left)
# 左子树为左叶子节点,即左子节点不为空,同时左子节点的左右子节点为空
if root.left != None and not root.left.left and not root.left.right:
left_num = root.left.val
# 右
right_num = self.sumOfLeftLeaves(root.right)
# 中
res = left_num + right_num
return res
四、222.完全二叉树的节点个数
题目链接:222. 完全二叉树的节点个数 - 力扣(LeetCode)
文章讲解:222.完全二叉树的节点个数 | 代码随想录 (programmercarl.com)
视频讲解:要理解普通二叉树和完全二叉树的区别! | LeetCode:222.完全二叉树节点的数量_哔哩哔哩_bilibiliCarl说:需要了解,普通二叉树 怎么求,完全二叉树又怎么求
"""
普通二叉树解法
"""
# 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 countNodes(self, root: Optional[TreeNode]) -> int:
res = []
def dfs(node):
if node is None:
return
dfs(node.left) # 左
dfs(node.right) # 右
res.append(node.val) # 中
dfs(root)
return len(res)
完全二叉树思路:满二叉树节点数为,判断左子树和右子树是否为满二叉树(左和右深度相等),相加最后再加根节点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:
# 1. 确定递归函数的参数和返回值
def getnum(self, node):
# 2. 确定终止条件
if not node:
return 0
# 终止条件2,判断是否为满二叉树
# 定义两个指针分别遍历左右两侧深度
left = node.left
right = node.right
leftdepth, rightdepth = 0, 0
# 计算左侧深度
while left:
left = left.left
leftdepth += 1
# 计算右侧深度
while right:
right = right.right
rightdepth += 1
# 判断是否为满二叉树,即左右两侧深度是否相等
if leftdepth == rightdepth:
return 2 ** (leftdepth + 1) - 1
# return (2 << leftdepth) - 1 也可以
# 3. 确定单层递归的逻辑
left_num = self.getnum(node.left) # 左
right_num = self.getnum(node.right) # 右
res = left_num + right_num + 1 # 中
return res
def countNodes(self, root: Optional[TreeNode]) -> int:
return self.getnum(root)
Note:运算符 "<<" 表示左移位操作符,假设leftdepth = 3,那么 2 << leftdepth = 2 * 2 ^ 3 = 16