导语
leetcode刷题笔记记录,本篇博客记录二叉树部分的题目,主要题目包括:
- 104.二叉树的最大深度(opens new window)
- 111.二叉树的最小深度
- 559 n叉树的最大深度
- 222 完全二叉树的节点个数
知识点
二叉树的高度与深度
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
- Leetcode上所有题目深度和高度都从1开始
完全二叉树
一个二叉树是完全二叉树当且仅当满足以下两个条件:
- 所有的层(除了最后一层外)都被完全填满。这意味着每一层(从根开始,直到倒数第二层)都有可能的最大节点数。
- 在最后一层,所有的节点都尽可能集中在左边,即如果最后一层不是完全填满的,那么空缺的位置应该都在最右边。
根据这种定义,完全二叉树的所有节点都有一个唯一的位置,与它们在数组中的索引相对应(如果将二叉树的节点存储在数组中,并按层次遍历的顺序)。这种特性使得完全二叉树经常被用于实现堆数据结构。
Leetcode 104 二叉树的最大深度
题目描述
给定一个二叉树 root ,返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 3
解法
根节点的高度就是二叉树的最大深度,这道题目等价于求最大高度,所以可以采用后序遍历来方便的实现。
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
return self.getMaxHeight(root)
def getMaxHeight(self, root):
if not root: return 0;
leftHeight = self.getMaxHeight(root.left)
rightHeight = self.getMaxHeight(root.right)
return 1 + max(leftHeight, rightHeight)
Leetcode 559 n叉树的最大深度
题目描述
给定一个 N 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。 N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。
示例 1:
输入: root = [1,null,3,2,4,null,5,6]
输出: 3
解法
与二叉树类似,这里的n叉树则需要借助一个数组heights来收集这n个children的高度,同时如果一个节点没有children,那么应该返回1。
class Solution:
def maxDepth(self, root: 'Node') -> int:
return self.getMaxHeight(root)
def getMaxHeight(self, root):
if not root: return 0
if not root.children: return 1
heights = []
for child in root.children:
height = self.getMaxHeight(child)
heights.append(height)
return 1+max(heights)
Leetcode 111 二叉树的最小深度
题目描述
给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明: 叶子节点是指没有子节点的节点。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 2
解法
这个题目如果直接套用最大深度的代码,只改max为min的话会导致错误,因为如果这样,代码会统计到某个缺少左孩子或右孩子的节点就停止,而不是叶子节点,比如下面的情况下,回直接返回1(因为根节点没有左子树)。
为此,需要在最终返回值时进行判断,避免掉这种情况,具体代码如下:
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
return self.getMinHeight(root)
def getMinHeight(self, root):
if not root: return 0;
leftHeight, rightHeight = self.getMinHeight(root.left), self.getMinHeight(root.right)
if leftHeight == 0 and rightHeight != 0:
return 1+rightHeight
elif leftHeight != 0 and rightHeight == 0:
return 1+leftHeight
else:
return 1+min(leftHeight, rightHeight)
Leetcode 222 完全二叉树的节点个数
题目描述
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
示例 1:
输入: root = [1,2,3,4,5,6]
输出: 6
解法
这道题完全可以采用层次遍历法,代码如下:
from collections import deque
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
queue = deque()
count = 0
if root:
queue.append(root)
while queue:
size = len(queue)
for _ in range(size):
node = queue.popleft()
count += 1
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
return count
但这样的复杂度是,而且没有利用好完全二叉树的性质。完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
- 对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
- 对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
具体实现代码如下:
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
left, right = root.left, root.right
left_depth, right_depth = 0, 0
while left:
left = left.left
left_depth += 1
while right:
right = right.right
right_depth += 1
if left_depth == right_depth:
return 2 ** (left_depth+1) - 1
left_num = self.countNodes(root.left)
right_num = self.countNodes(root.right)
result = left_num + right_num + 1
return result