🚀蓝蓝计算机考研算法-day21求二叉树最小深度

174 阅读3分钟

Day13 2023/03/13

难度:简单

题目

30、给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。例如:

image.png

示例

输入:1 2 3 4 5 # 6 # # 7 # # # (层序遍历的方式创建链表)
输出:最小深度为:3

运行实例

image.png

思路


本题求得是最小深度,之前这篇博客里求的得是最大深度😎蓝蓝计算机考研算法-day19二叉树深度 - 掘金 (juejin.cn),并且是完全基于深度优先算法来实现得。但是本题求最小深度,并不是 在求最大深度代码的基础上,简单的修改一下返回值,让每次递归返回最小值就可以得(千万注意这里❌),如果完全居于深度优先算法实现求最小深度,可能会出现 "路径选择错误得问题"(划重点❗),如下图:
d6d1ade06842b8d26be94933a9c5123.jpg

我们可以看到实际得最短路径应为:1->2->4 和 1->3->6这两条,最小深度应该为3,但是如果仅仅在求最大深度得基础上,简单得修改一下返回值,则会出现路径选择 判断错误的情况,错误得选择1->3->null 为最短路径,则最短深度就变成了2,所以在求最大深度代码得基础上,不仅得修改一下返回值,还需要添加附加判断条件,来规避这种错误的路径。

关键点


  • 上文求二叉树最大深度的时候,使用的是先序遍历的方式创建的二叉树,这种方式输入序列比较麻烦,需要自己先将二叉树转成先序序列,有写同学可能不太喜欢,所以今天求最短路径,就换成更加符合直觉的层序遍历的方式创建二叉树(贴心💖)。
  • 其次,我并没有采用辅助队列加非递归的方式实现层序序列构造二叉树,仍然采用递归的方式,只不过这里利用了满二叉树的性质,如果左孩子存在,则编号为2i; 如果右孩子存在,则编号为2i+1。(知识点✅)

算法实现


c++代码实现-二叉树最小深度

#include <iostream>
#include <string>
#include <vector>
using namespace std;

// 定义二叉树节点
typedef struct BiTNode {
  string data;           // 数据域
  BiTNode *left, *right; // 左右节点
  BiTNode(string val) : data(val), left(nullptr), right(nullptr){};
} BiTNode, *BiTree;

// 创建二叉树(按照层序遍历的方式)
void CreateBTree(BiTree &T,vector<string> data, int i, int n) {
    if (i >= n ||data[i] == "#")   T = nullptr; // val等于#代表该节点不存在
    else {
        T = new BiTNode(data[i]);           // 申请新节点,按照层序遍历的方式
        // 这里i为数组下标,所以计算编号在原基础上加1
        CreateBTree(T->left,data,2*i+1,n);  // 对于满二叉树来说,若有左孩子,则编号为2i
        CreateBTree(T->right,data,2*i+2,n); // 对于满二叉树来说,若有右孩子,则编号为2i+1
    }
}

// 计算二叉树最小深度 采用DFS方式(属于基操)
int TreeMinDepth (BiTree T) {
    if (!T) return 0;
    int LDepth = TreeMinDepth(T->left);
    int RDepth = TreeMinDepth(T->right);
    // 解决最短路径误判的情况
    if (!T->left && T->right) LDepth = RDepth;
    if (!T->right && T->left) RDepth = LDepth;
    return LDepth < RDepth ? LDepth + 1 : RDepth + 1;
}

int main() {
  BiTree T;
  vector<string> data = {}; // 数据
  string val; // 输入值
  while (cin >> val) {
    data.push_back(val);
    if (getchar() == '\n') break;
  }
  CreateBTree(T, data, 0, data.size()); //创建二叉树
  int deep = TreeMinDepth(T);
  cout << "最小深度为:" << deep;
  return 0;
  }
  • 时间复杂度 O(n)O(n)--- 递归访问二叉树所有节点 ,其中n为节点总数
  • 空间复杂度 O(n)O(n)--- 最坏情况下二叉树呈现链状,递归栈深度等于二叉树节点数n

总结

  • 递归是个好东西,但是要慎用,不管是理解还是模拟代码运行过程,都比较让人头痛,本题就是这样,一不注意,就可能直接简单的修改一下求最大深度的代码,然后一运行结果,就让人摸不着头脑,不理解哪里有问题!!!(🤷‍♀️💥)