欢迎关注千羽的公众号
“
Leetcode : https://leetcode-cn.com/problems/er-cha-shu-de-shen-du-lcof/
“
GitHub : https://github.com/nateshao/leetcode/blob/main/algo-notes/src/main/java/com/nateshao/sword_offer/topic_41_maxDepth/Solution.java
剑指 Offer 55 - I. 二叉树的深度
“
题目描述 :输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
难度:简单
例如:给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
方法一:递归 (后序遍历)
“
树的遍历方式总体分为两类:深度优先搜索(DFS)、广度优先搜索(BFS);
- 常见的 DFS : 先序遍历、中序遍历、后序遍历(左右根);
- 常见的 BFS : 层序遍历(即按层遍历)。
- 树的后序遍历 / 深度优先搜索往往利用 递归 或 栈 实现
- 关键点: 此树的深度和其左(右)子树的深度之间的关系。显然,此树的深度 等于 左子树的深度 与 右子树的深度 中的 最大值 +1 。
算法解析:
- 终止条件: 当
root
为空,说明已越过叶节点,因此返回 深度 0 。 - 递推工作:本质上是对树做后序遍历。
- 计算节点 root 的 左子树的深度 ,即调用 maxDepth(root.left);
- 计算节点 root 的 右子树的深度 ,即调用 maxDepth(root.right);
- 返回值: 返回 此树的深度 ,即
max(maxDepth(root.left), maxDepth(root.right)) + 1
。
- In other words, 考虑以下几种情况:
如果二叉树为空,深度为 0;如果二叉树只有根节点,深度为 1;如果二叉树的根节点只有左子树,深度为左子树的深度加 1;如果二叉树的根节点只有右子树,深度为右子树的深度加 1;如果二叉树的根节点既有左子树又有右子树,深度为左右子树深度的最大者再加 1。
复杂度分析:
- 时间复杂度 O(N):N 为树的节点数量,计算树的深度需要遍历所有节点。
- 空间复杂度 O(N) :最差情况下(当树退化为链表时),递归深度可达到 N 。
package com.nateshao.one_question_per_day.code_2022.january;
/**
* @date Created by 邵桐杰 on 2022/1/22 22:56
* @微信公众号 千羽的编程时光
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class Solution_2022_01_22_maxDepth {
/**
* 方法一:递归解法
* 思路:利用递归遍历分别返回左右子树深度
*
* @param root
* @return
*/
public int maxDepth(TreeNode root) {
// return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right) + 1);
if (root == null) return 0;
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left, right) + 1;
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
}
Golang
/* go 语言没有三目运算符 */
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
方法二:非递归一一层序遍历(BFS)
- 树的层序遍历 / 广度优先搜索往往利用 队列 实现。
- 关键点: 每遍历一层,则计数器 +1 ,直到遍历完成,则可得到树的深度。
算法解析:
- 特例处理: 当
root
为空,直接返回 深度 0 。 - 初始化: 队列
queue
(加入根节点 root
),计数器 res = 0
。 - 循环遍历: 当
queue
为空时跳出。
- 初始化一个空列表
tmp
,用于临时存储下一层节点; - 遍历队列:遍历
queue
中的各节点 node
,并将其左子节点和右子节点加入 tmp
; - 更新队列:执行
queue = tmp
,将下一层节点赋值给 queue
; - 统计层数:执行
res += 1
,代表层数加 1;
/**
* 方法二:层序遍历(BFS)
* @param root
* @return
*/
public int maxDepth2(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int res = 0;
while (!queue.isEmpty()) {
res++;
int n = queue.size();
for (int i = 0; i < n; i++) {
TreeNode node = queue.poll();
if (node.left != null) queue.add(node.left);
if (node.right != null) queue.add(node.right);
}
}
return res;
}
Golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxDepth(root *TreeNode) int {
// 边界
if root == nil {
return 0
}
depth := 0
var queue []*TreeNode
queue = append(queue, root)
// bfs
for len(queue) > 0 {
length := len(queue)
for i := 0; i < length; i++ {
cur := queue[0]
queue = queue[1:]
if cur.Left != nil {
queue = append(queue, cur.Left)
}
if cur.Right != nil {
queue = append(queue, cur.Right)
}
}
depth += 1
}
return depth
}
参考链接:
- https://leetcode-cn.com/problems/er-cha-shu-de-shen-du-lcof/solution/mian-shi-ti-55-i-er-cha-shu-de-shen-du-xian-xu-bia/
- https://leetcode-cn.com/problems/er-cha-shu-de-shen-du-lcof/solution/jian-zhi-offer-55-i-er-cha-shu-de-shen-du-di-gui-c/
END
革命尚未成功,同志仍需努力,冲冲冲