相关推荐
python coding with ChatGPT 打卡第12天| 二叉树:理论基础
python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历
python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历
python coding with ChatGPT 打卡第15天| 二叉树:翻转二叉树、对称二叉树
文章目录
- 完全二叉树的节点个数
- Key Points
- 相关题目
- 视频讲解
- 重点分析
- 平衡二叉树
- Key Points
- 相关题目
- 视频讲解
- 重点分析
- 拓展
- 二叉树的所有路径
- 相关题目
- 视频讲解
- 重点分析
- 左叶子之和
- Key Points
- 相关题目
- 视频讲解
- 重点分析
完全二叉树的节点个数
Key Points
- 利用完全二叉树的性质:完全二叉树是一种特殊的二叉树,除了最底层,其它每一层都被完全填满,而且最底层从左到右填入节点。
相关题目
222. 完全二叉树的节点个数
视频讲解
理解普通二叉树和完全二叉树的区别
重点分析
首先,我们来思考一下如何递归地解决这个问题,再考虑是否有更高效的方法。
方法一:
def countNodes(root):if not root:return 0count_left = countNodes(root.left)count_right = countNodes(root.right)return count_left + count_right + 1
方法二:(迭代法遍历节点)
def countNodes(root):if not root:return 0stack_record = [root]count = 0while stack_record:node = stack_record.pop()count += 1if node.right:stack_record.append(node.right)if node.left:stack_record.append(node.left)return count
解决这个问题的关键是利用完全二叉树的性质。
完全二叉树的高度可以通过连续地访问左子树
来确定。
方法三:
如果左子树的高度等于右子树的高度,则为满二叉树
def get_height(node):if not node:return 0height = 0while node:node = node.leftheight += 1return heightdef get_count(height):num = 2**height - 1return numdef countNodes(root):if not root:return 0left_height = get_height(root.left)right_height = get_height(root.right)if left_height > right_height:right_count = get_count(right_height)left_count = countNodes(root.left)else:left_count = get_count(left_height)right_count = countNodes(root.right)return 1+left_count+right_count
方法四:
在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。
def countNodes(root):if not root:return 0left = root.leftright = root.rightleft_height = 1right_height = 1while left:left_height += 1left = left.leftwhile right:right_height += 1right = right.rightif left_height == right_height:return get_count(left_height)return countNodes(root.left) + countNodes(root.right) + 1
class Solution: # 利用完全二叉树特性def countNodes(self, root: TreeNode) -> int:if not root: return 0count = 1left = root.left; right = root.rightwhile left and right:count += 1left = left.left; right = right.rightif not left and not right: # 如果同时到底说明是满二叉树,反之则不是return 2**count-1return 1 + self.countNodes(root.left) + self.countNodes(root.right)
平衡二叉树
Key Points
判断一个二叉树是否是高度平衡的,其定义是:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是高度平衡的二叉树。
相关题目
110. 平衡二叉树
视频讲解
后序遍历求高度
重点分析
def isBalanced(root):if not root:return Trueheight = get_height(root)if height == -1:return Falsereturn Truedef get_height(node):if not node:return 0left_height = get_height(node.left)right_height = get_height(node.right)if left_height == -1 or right_height == -1:return -1if abs(left_height - right_height) > 1:return -1return 1 + max(left_height, right_height)
这种方法的好处是它在计算高度的同时检查平衡性
,只需遍历树一次,提高了效率。
拓展
二叉树的所有路径
相关题目
257. 二叉树的所有路径
视频讲解
递归中带着回溯
重点分析
方法一:
递归法
class Solution:def binaryTreePaths(self, root: TreeNode) -> [str]:if not root:return []paths = []self._findPaths(root, "", paths)return pathsdef _findPaths(self, node, path, paths):# 更新当前路径currentPath = path + str(node.val)# 如果是叶子节点,添加路径到结果列表if not node.left and not node.right:paths.append(currentPath)else:# 如果不是叶子节点,递归遍历子节点if node.left:self._findPaths(node.left, currentPath + "->", paths)if node.right:self._findPaths(node.right, currentPath + "->", paths)# 示例使用
# 假设我们有一个二叉树,我们可以创建这个树的节点,并调用上述函数
# 比如:
# 1
# / \
# 2 3
# \
# 5
# root = TreeNode(1)
# root.left = TreeNode(2)
# root.right = TreeNode(3)
# root.left.right = TreeNode(5)
# solution = Solution()
# print(solution.binaryTreePaths(root))
方法二:
迭代法(更好理解)
class Solution:def binaryTreePaths(self, root: TreeNode) -> [str]:if not root:return []paths = []stack = [(root, str(root.val))] # 初始化栈,包含节点和路径while stack:node, path = stack.pop() # 取出当前节点和路径# 如果是叶子节点,添加路径到结果列表if not node.left and not node.right:paths.append(path)else:# 如果不是叶子节点,更新路径并将子节点加入栈if node.right:stack.append((node.right, path + "->" + str(node.right.val)))if node.left:stack.append((node.left, path + "->" + str(node.left.val)))return paths
在这个迭代版本中,我们使用了一个栈来存储每个节点以及从根节点到该节点的路径。这种方法模拟了递归过程的深度优先搜索(DFS)前序遍历,确保了我们能够访问到每一个叶子节点,并在到达叶子节点时记录完整的路径。
这种迭代方法提供了一种不使用系统调用栈的递归的替代方案,对于深度非常大的树来说,可以避免递归导致的栈溢出问题。
左叶子之和
Key Points
- 要注意是判断左叶子,不是二叉树左侧节点
- 判断是否是左叶子,需要通过父节点来判断
相关题目
404. 左叶子之和
视频讲解
总有一些规则让你找不到北
重点分析
方法一:
递归法:
def sumOfLeftLeaves(root):if not root:return 0res = 0if isLeave(root.left):res += root.left.valres += sumOfLeftLeaves(root.right)else:res += sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right)return resdef isLeave(node):if node:if not node.left and not node.right:return Truereturn False
方法二:
迭代法(更好理解)
def sumOfLeftLeaves(root):if not root:return 0stack_record = [root]res = 0while stack_record:node = stack_record.pop()if isLeave(node.left):res += node.left.valif node.right:stack_record.append(node.right)else:if node.right:stack_record.append(node.right)if node.left:stack_record.append(node.left)return res
精简版:
def sumOfLeftLeaves(root):if not root:return 0stack_record = [root]res = 0while stack_record:node = stack_record.pop()if isLeave(node.left):res += node.left.valif node.right:stack_record.append(node.right)if node.left:stack_record.append(node.left)return res