题目
方法一-递归(DFS)
算法思路
若已知左子树和右子树的深度 a a a 和 b b b,则该二叉树的深度为 m a x ( a , b ) + 1 max(a, b)+1 max(a,b)+1,左右子树的深度以同样的方式计算,递归访问到空结点时退出。
具体代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n为二叉树结点总数
- 空间复杂度: O ( n ) O(n) O(n)。递归函数需要额外的栈空间,栈空间大小取决于递归的深度。最坏情况下,即树退化为链表时,递归深度达到 n。
方法二-广度优先遍历-I
算法思路
在广度优先遍历基础上做一些修改,广度优先遍历的队列里存放的是当前层的所有结点,拓展到下一层时,不同于广度优先遍历的每次取一个结点,我们将所有结点都取出,拓展的次数就等于二叉树的深度。
具体代码
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)return 0;//空树
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);//根节点入队
int res = 0;//记录拓展次数,即树的深度
while(!queue.isEmpty()){
int s = queue.size();//队列中节点数
while(s > 0){
//当前层的所有节点依次出队
TreeNode node = queue.poll();
//拓展到下一层(子节点入队)
if(node.left != null)queue.offer(node.left);
if(node.right != null)queue.offer(node.right);
s--;
}
res++;//每拓展一层,树深加1
}
return res;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n为二叉树结点总数
- 空间复杂度: O ( n ) O(n) O(n)。使用的额外空间大小取决于结点最多的一层的结点总数,最坏情况下,即树平衡时,队列会同时存储 n / 2 n/2 n/2 个节点。
方法三-广度优先遍历-II
算法思路
与方法二的原理相同,只是往下一层拓展时不是一个一个节点地依次打印,而是新建一个列表临时存储下一层的节点。
空树处理和初始化、返回值均与方法二一致。
循环过程:
- 初始化一个空列表
tmp
; - 遍历队列:将队列
queue
中的各个节点的左右子节点加入tmp
; - 更新队列:将下一层节点赋给队列
queue
,即执行queue = tmp
; - 统计深度:
res++
具体代码
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)return 0;//空树
Queue<TreeNode> queue = new LinkedList<>(), tmp;
queue.offer(root);//根节点入队
int res = 0;//记录拓展次数,即树的深度
while(!queue.isEmpty()){
tmp = new LinkedList<>();
for(TreeNode node : queue){
if(node.left != null)tmp.offer(node.left);
if(node.right != null)tmp.offer(node.right);
}
queue = tmp;//更新队列
res++;//每拓展一层,树深加1
}
return res;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n为二叉树结点总数
- 空间复杂度: O ( n ) O(n) O(n)。使用的额外空间大小取决于结点最多的一层的结点总数,最坏情况下,即树平衡时,队列会同时存储 n / 2 n/2 n/2 个节点。