一、需求
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
**说明:**叶子节点是指没有子节点的节点。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:2
示例 2:
输入:root = [2,null,3,null,4,null,5,null,6]
输出:5
提示:
- 树中节点数的范围在
[0, 105]
内 -1000 <= Node.val <= 1000
二、思路分析图【递归】
三、代码
公共代码
TreeNode(节点类)
package com.bessky.pss.wzw.SuanFa;
import java.util.ArrayList;
import java.util.List;
/**
* 树节点类
*
* @author 王子威
* @date 2022/7/27
*/
public class TreeNode
{
int val;
TreeNode left;
TreeNode right;
TreeNode()
{
}
TreeNode(int val)
{
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right)
{
this.val = val;
this.left = left;
this.right = right;
}
/**
* 遍历显示
*
* @return
*/
public String display()
{
// 创建存储先序遍历后的结果
List<Integer> results = new ArrayList<>();
// 调用:递归方法
this.inorder(this, results);
return results.toString();
}
/**
* 递归方法体
*
* @param root
* @param results
*/
public void inorder(TreeNode root, List<Integer> results)
{
if (root == null)
{
return;
}
// 调用:当最左时就存储 || 或左没有时存储
results.add(root.val);
// 调用:递归方法(先把最左边的拿到)
inorder(root.left, results);
// 调用:递归方法(左没有时就递归右边)
inorder(root.right, results);
}
}
(一)递归方案
①数据初始化/调用函数
/**
* 入口
* 111、二叉树的最小深度
* 输入:
* TreeNode root = [3,9,20,null,null,15,7]
* 输出:
* 二叉树的最小深度是2
* 二叉树的最小深度(优化)是2
* 解释:
* 1.递归
*/
@Test
public void suanfa25()
{
TreeNode root = new TreeNode(3, new TreeNode(9), new TreeNode(20, new TreeNode(15), new TreeNode(7)));
System.out.println("二叉树的最小深度是" + minDepth(root));
System.out.println("二叉树的最小深度(优化)是" + minDepthOptimize(root));
System.out.println("二叉树的最小深度(Morris)是" + minDepthMorris(root));
}
②递归方案
/**
* 递归方案
*
* @param root
* @return
*/
private int minDepth(TreeNode root)
{
// 如果root为空就返回0
if (root == null) return 0;
// 递归条件里的三种情况
// 1.左孩子和右孩子都为空的情况,说明到达了叶子节点,直接返回1即可
if (root.left == null && root.right == null) return 1;
// 2.如果左孩子和右孩子其中一个为空,那么需要返回比较大的那个孩子的深度
int m1 = minDepth(root.left);
int m2 = minDepth(root.right);
// 到这里其中一个节点为空,说明m1和m2有一个必然为0,所以可以返回m1 + m2 + 1
if (root.left == null || root.right == null) return m1 + m2 + 1;
// 3.最后一种情况,也就是左右孩子都不为空,返回最小深度 + 1即可
return Math.min(m1,m2) + 1;
}
③递归方案(优化)
/**
* 递归方案(优化)
*
* @param root
* @return
*/
private int minDepthOptimize(TreeNode root)
{
// 如果root为空就返回0
if (root == null) return 0;
// 1.左孩子和右孩子都为空的情况,说明到达了叶子节点,直接返回1即可
if (root.left == null && root.right == null) return 1;
// 2.如果左孩子和右孩子其中一个为空,那么需要返回比较大的那个孩子的深度
int m1 = minDepthOptimize(root.left);
int m2 = minDepthOptimize(root.right);
// 到这里其中一个节点为空,说明m1和m2有一个必然为0,所以可以返回m1 + m2 + 1
return (root.left == null || root.right == null) ? m1 + m2 + 1 : Math.min(m1,m2) + 1;
}
④Morris遍历法
/**
* Morris遍历法
*
* @param root
* @return
*/
private int minDepthMorris(TreeNode root) {
if (root == null) {
return 0;
}
TreeNode cur = root;
TreeNode mostRight = null;
int min = Integer.MAX_VALUE;
int level = 0; //cur在第几层
while (cur != null) {
mostRight = cur.left;
if (mostRight != null) {
int count = 1;
while (mostRight.right != null && mostRight.right != cur) {
count++;
mostRight = mostRight.right;
}
if (mostRight.right == null) {
mostRight.right = cur;
level++;// 当前第一次到达
cur = cur.left;
} else { // 当前第二次到达
//计算高度是否要回退,要回退多少
if (mostRight.left == null) {
min = Math.min(min, level);
}
level -= count;
mostRight.right = null;
cur = cur.right;
}
} else {
level++;// 当前第一次到达
cur = cur.right;
}
}
//头的右边界还未判断
int count = 1;
TreeNode tmp = root;
while (tmp.right != null) {
count++;
tmp = tmp.right;
}
if (tmp.left == null) { //是叶节点,判断其深度
min = Math.min(min, count);
}
return min;
}
⑤结果图
作者:王子威
四、总结
- 学习了二叉树的最小深度
- 有丝丝进步,递归的逻辑有些清晰了,但是自己写还是有难度的,感觉还是很迷,变下就乱了,还带提高
- left+right+1这里容易卡点,这里其实为了返回其中有一个为空或两都为空的情况,因为是null,所以会返回0,所以加起来也没事,得到的还是非null值+1,和我判断为空并返回对方值+1 的思路是一致的
- 只有在两个子节点都在的情况下才会去比较min的值+1
- 叶子节点是指没有子节点的节点。
- 算法兴趣+1 总:25
- 加强了对算法的分析能力