104-二叉树-二叉树的最大深度

树 | 深度优先搜索 | 广度优先搜索 | 二叉树

深度优先搜索(DFS,Depth-First Search)是一种用于遍历或搜索树或图的算法。DFS 从根节点开始,沿着树的深度尽可能向下搜索,直到到达叶子节点,然后回溯到最近的分支点,继续探索其他路径。

DFS 的基本概念

  1. 遍历方式

    • DFS 可以使用递归或迭代的方式实现。
    • 递归方式自然地利用了函数调用栈,而迭代方式通常使用显式栈来模拟递归的调用。
  2. 应用场景

    • DFS 适用于解决很多问题,如路径查找、连通性检测、拓扑排序、图的遍历、求解迷宫等。
    • 在二叉树中,DFS 常用于遍历树的节点,例如前序遍历、中序遍历、后序遍历等。

DFS 的一般解题流程

在二叉树场景下,DFS 的一般解题流程可以分为以下几个步骤:

  1. 选择遍历方式

    • 确定使用递归还是迭代来实现 DFS。
    • 根据问题的要求选择遍历顺序(前序、中序、后序)。
  2. 定义递归函数或迭代结构

    • 如果使用递归,定义一个函数,接收当前节点及其他必要参数(如结果数组)。
    • 如果使用迭代,初始化一个栈来存储节点。
  3. 递归或迭代逻辑

    • 递归
      • 如果当前节点为空,返回(终止条件)。
      • 处理当前节点(如记录值、进行计算等)。
      • 递归访问左子树。
      • 递归访问右子树。
    • 迭代
      • 使用循环,直到栈为空。
      • 将当前节点压入栈,访问左子节点。
      • 弹出栈顶节点,处理该节点,然后访问右子节点。
  4. 处理结果

    • 根据需要收集和处理遍历结果。

在二叉树中的 DFS 示例

我们以二叉树的前序遍历为例,说明 DFS 的具体实现及其流程。

示例二叉树
        1
       / \
      2   3
     / \
    4   5
前序遍历的步骤

前序遍历的顺序是:根节点 -> 左子树 -> 右子树。

递归实现

const preorderTraversal = function(root) {
    const res = []; // 用于存储结果

    const dfs = (node) => {
        if (!node) return; // 终止条件
        res.push(node.val); // 处理当前节点
        dfs(node.left); // 递归访问左子树
        dfs(node.right); // 递归访问右子树
    };

    dfs(root); // 从根节点开始
    return res; // 返回结果
};

迭代实现

const preorderTraversal = function(root) {
    const res = []; // 用于存储结果
    const stk = []; // 初始化栈

    if (root) stk.push(root); // 如果根节点不为空,压入栈

    while (stk.length) {
        const node = stk.pop(); // 弹出栈顶节点
        res.push(node.val); // 处理当前节点
        if (node.right) stk.push(node.right); // 先压入右子节点
        if (node.left) stk.push(node.left); // 再压入左子节点(确保左子节点先被处理)
    }

    return res; // 返回结果
};

要计算二叉树的最大深度,我们可以使用深度优先搜索(DFS)的方法。下面我将详细分析这个问题的解题思路,包括代码实现和执行过程。

问题定义

最大深度是指从根节点到最远叶子节点的最长路径上的节点数。也就是说,我们需要找到从根节点到达叶子节点的路径中,节点的数量最多的那条路径。

解题思路

  1. 终止条件

    • 如果当前节点为空(即 rootnull),则该路径的深度为 0
  2. 递归返回值

    • 如果节点不为空,递归计算其左子树和右子树的最大深度。
    • 返回左右子树深度的最大值加 1(表示当前节点本身)。
  3. 执行过程

    • 递归会一直向下遍历到叶子节点,然后开始回溯,计算每个节点的深度。
  4. 时间复杂度

    • 由于每个节点只会被访问一次,时间复杂度为 O(n),其中 n 是树中节点的数量。

代码实现

下面是计算二叉树最大深度的 JavaScript 实现:

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
    // 终止条件:如果当前节点为空,返回深度 0
    if (!root) {
        return 0;
    } else {
        // 递归计算左右子树的深度
        const left = maxDepth(root.left);
        const right = maxDepth(root.right);
        // 返回左右子树深度的最大值加 1
        return Math.max(left, right) + 1;
    }
};

执行过程示例

我们以以下二叉树为例,来演示 maxDepth 函数的执行过程:

        1
       / \
      2   3
     / \
    4   5
递归调用过程
  1. 初始调用

    • maxDepth(1),当前节点是 1
  2. 访问左子树

    • 调用 maxDepth(2),当前节点是 2
  3. 继续访问左子树

    • 调用 maxDepth(4),当前节点是 4
    • maxDepth(4.left)maxDepth(4.right) 都返回 0(叶子节点)。
    • 返回 Math.max(0, 0) + 1 = 1(节点 4 的深度为 1)。
  4. 返回到节点 2,访问右子树:

    • 调用 maxDepth(5),当前节点是 5
    • maxDepth(5.left)maxDepth(5.right) 都返回 0(叶子节点)。
    • 返回 Math.max(0, 0) + 1 = 1(节点 5 的深度为 1)。
  5. 返回到节点 2

    • 左子树深度为 1(节点 4),右子树深度为 1(节点 5)。
    • 返回 Math.max(1, 1) + 1 = 2(节点 2 的深度为 2)。
  6. 返回到节点 1,访问右子树:

    • 调用 maxDepth(3),当前节点是 3
    • maxDepth(3.left)maxDepth(3.right) 都返回 0(叶子节点)。
    • 返回 Math.max(0, 0) + 1 = 1(节点 3 的深度为 1)。
  7. 返回到节点 1

    • 左子树深度为 2(节点 2),右子树深度为 1(节点 3)。
    • 返回 Math.max(2, 1) + 1 = 3(根节点 1 的深度为 3)。

最终结果

通过上述过程,得到的最大深度为 3,即从根节点到最远叶子节点的最长路径包含 3 个节点(1 -> 2 -> 41 -> 2 -> 5)。


BFS待定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值