目录
LeetCode104. 二叉树的最大深度
链接:104. 二叉树的最大深度 - 力扣(LeetCode)
方法一:递归解法
1. 思路
背景知识补充
什么是二叉树的深度和高度?
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数后者节点数(取决于高度从0开始还是从1开始)
💡 根节点的高度就是二叉树的最大深度
Example:
求二叉树的高度和深度分别用什么遍历方式?
求高度是从下往上数的,收集左右孩子信息,向上返回的这类思路都需要用到后序遍历,所以求高度用后序遍历(左右中);求深度是从上往下数的,因此用前序遍历(中左右)即可。
回归讨论本题
本题要求的是二叉树的最大深度,所以可以求深度;同时根节点的高度就是二叉树的最大深度,所以也可以求根节点的高度。
可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。
2. 代码实现
用后序遍历(左右中)来计算树的高度。
- 确定递归函数的参数和返回值:
参数就是传入树的根节点,返回就返回这棵树的深度,所以返回值为int类型。代码如下:
class solution:
def maxdepth(self, root: treenode) -> int:
return self.getdepth(root)
def getdepth(self, node):
- 确定终止条件:如果为空节点的话,就返回0,表示高度为0。
if not node: return 0
- 确定单层递归的逻辑:
先求它的左子树的深度,再求的右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。
leftdepth = self.getdepth(node.left) #左
rightdepth = self.getdepth(node.right) #右
depth = 1 + max(leftdepth, rightdepth) #中
return depth
整体Python代码如下:
# 后序的递归解法 左右中
# 根节点的高度就是二叉树的最大深度
# time:O(N);space:O(N)
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
return self.getHeight(root)
def getHeight(self,node):
if node == None: return 0 # base case
leftHeight = self.getHeight(node.left) # 左
rightHeight = self.getHeight(node.right) # 右
Height = max(leftHeight,rightHeight) + 1 # 中
return Height
精简代码如下
class solution:
def maxdepth(self, root: treenode) -> int:
if not root:
return 0
return 1 + max(self.maxdepth(root.left),
self.maxdepth(root.right))
3. 复杂度分析
时间复杂度:O(n)
其中 n 为二叉树节点的个数。每个节点在递归中只被遍历一次;
空间复杂度:O(height) = O(N)
其中height 表示二叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于二叉树的高度,平均情况下为O(logN),最大情况下,树为链式的,复杂度为O(N)
4. 思考
- 精简之后的代码根本看不出是哪种遍历方式,也看不出递归三部曲的步骤,所以如果对二叉树的操作还不熟练,尽量不要直接照着精简代码来学;
- 本题的递归法也可以用前序遍历来写,但是会复杂很多,建议之后学有余力当做练习;这里贴一份前序遍历的C++代码;
class solution {
public:
int result;
void getdepth(treenode* node, int depth) {
result = depth > result ? depth : result; // 中
if (node->left == NULL && node->right == NULL) return ;
if (node->left) { // 左
depth++; // 深度+1
getdepth(node->left, depth);
depth--; // 回溯,深度-1
}
if (node->right) { // 右
depth++; // 深度+1
getdepth(node->right, depth);
depth--; // 回溯,深度-1
}
return ;
}
int maxdepth(treenode* root) {
result = 0;
if (root == NULL) return result;
getdepth(root, 1);
return result;
}
};
# 简化后如下
class solution {
public:
int result;
void getdepth(treenode* node, int depth) {
result = depth > result ? depth : result; // 中
if (node->left == NULL && node->right == NULL) return ;
if (node->left) { // 左
getdepth(node->left, depth + 1);
}
if (node->right) { // 右
getdepth(node->right, depth + 1);
}
return ;
}
int maxdepth(treenode* root) {
result = 0;
if (root == 0) return result;
getdepth(root, 1);
return result;
}
};
方法二:迭代解法
1. 思路
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度,如图所示:
所以这道题的迭代法就是一道模板题,可以使用二叉树层序遍历的模板来解决的。
2. 代码实现
# 迭代解法 层序遍历
# 二叉树的层数就是最大深度
# time:O(N);space:O(N)
from collections import deque
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if root == None: return 0