Maximum Depth of Binary Tree -- LeetCode

本文介绍了LeetCode上的二叉树最大深度问题的两种解法:递归与非递归。递归方法简洁,直接利用左右子树的最大深度。非递归采用层序遍历,适合直观理解。
原题链接: http://oj.leetcode.com/problems/maximum-depth-of-binary-tree/  

这是一道比较简单的树的题目,可以有递归和非递归的解法,递归思路简单,返回左子树或者右子树中大的深度加1,作为自己的深度即可,代码如下: 

public int maxDepth(TreeNode root) {
    if(root == null)
        return 0;
    return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
非递归解法一般采用层序遍历(相当于图的BFS),因为如果使用其他遍历方式也需要同样的复杂度O(n). 层序遍历理解上直观一些,维护到最后的level便是树的深度。代码如下: 
public int maxDepth(TreeNode root) {
    if(root == null)
        return 0;
    int level = 0;
    LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
    int curNum = 1; //num of nodes left in current level
    int nextNum = 0; //num of nodes in next level
    while(!queue.isEmpty())
    {
        TreeNode n = queue.poll();
        curNum--;
        if(n.left!=null)
        {
            queue.add(n.left);
            nextNum++;
        }
        if(n.right!=null)
        {
            queue.add(n.right);
            nextNum++;
        }
        if(curNum == 0)
        {
            curNum = nextNum;
            nextNum = 0;
            level++;
        }
    }
    return level;
}
总体来说我觉得这道题可以考核树的数据结构,也可以看看对递归和非递归的理解。相关的扩展可以是 Minimum Depth of Binary Tree .

<think>嗯,用户让我解释为什么这段代码叫做自底向上。让我先仔细看一下提供的代码。这是一个用C语言写的二叉树最大深度的递归解法。作者是灵茶山艾府,代码结构看起来挺典型的递归。 首先,我需要回忆一下二叉树遍历的两种常见方法:自顶向下和自底向上。自顶向下通常指的是在递归过程中,先处理当前节点,然后再递归处理子节点,比如前序遍历。而自底向上则是先递归到叶子节点,然后逐步返回处理,比如后序遍历。这个代码里的maxDepth函数,先递归调用左右子树,然后取最大值加1,明显是后序遍历的顺序,也就是先处理子节点再处理当前节点。所以这里可能就是因为这种后序的方式,导致被称为自底向上。 那问题来了,用户可能对递归的过程不太清楚,需要详细说明为什么递归的顺序决定了自底向上。比如,当函数递归到叶子节点的子节点(即NULL)时返回0,然后一步步返回到父节点,计算每个节点的深度。这个过程是从叶子节点开始,逐层向上计算深度,直到根节点。所以每个节点的深度都是基于其子节点的深度计算的,这符合自底向上的逻辑。 另外,用户可能混淆了自顶向下和自底向上的区别。例如,自顶向下可能在递归时传递当前的深度参数,比如在每一层递归中增加深度,直到叶子节点时比较最大值。而自底向上则是先得到子节点的深度,再计算当前节点的。所以这里的区别在于信息的传递方向:一个是向下传递参数,另一个是向上返回结果。 需要进一步解释代码的执行流程。比如,当root为NULL时返回0,否则递归计算左右子树的深度,取较大者加1。这个过程实际上是先深入到最底层(叶子节点的子节点),然后从那里开始返回深度值,逐层向上累加。因此,每个父节点的深度都依赖于子节点的结果,这种依赖关系导致了自底向上的计算方式。 可能用户的理解误区在于认为“自底向上”需要显式的从叶子节点开始处理,但递归的隐式栈实际上自动实现了这个过程。因为递归总是先处理最深的节点,然后回溯。所以虽然代码看起来像是从根节点开始,但实际的执行顺序是先到达底部,再逐步返回处理上层节点。 总结来说,这个递归方法被称为自底向上,是因为它先递归到叶子节点,然后从叶子节点开始计算深度,逐层返回到父节点,最终得到根节点的深度。这种方法利用递归栈的后序遍历特性,实现了从底层到顶层的深度计算。</think>这个递归解法被称为"自底向上"的原因,可以通过以下步骤理解: 1. **递归执行顺序** 代码采用的是后序遍历: $$ 左子树深度 \rightarrow 右子树深度 \rightarrow 当前节点深度 $$ 这保证了程序会先递归到二叉树的最底层(叶子节点),然后逐步向上计算每个父节点的深度。 2. **深度计算过程** 当遇到空节点时返回 0(递归终止条件),这相当于从树的最底层开始统计: $$\begin{aligned} 叶子节点深度 &= 1 \\ 父节点深度 &= max(左子树深度, 右子树深度) + 1 \\ 根节点深度 &= 最终结果 \end{aligned}$$ 3. **与自顶向下的对比** 如果是自顶向下方式,通常会通过参数传递当前深度,在递归过程中维护最大值。而本解法是通过子问题的解(子树深度)来构造原问题(整树深度)的解,这正是动态规划思想中的最优子结构特性。 4. **递归展开示例** 以简单二叉树 [3,9,20] 为例: ``` 3 ← 最后计算深度=3 / \ 9 20 ← 先计算这两个节点的深度=1 ``` 实际计算顺序是:9→20→3,完美体现了从底层向上传递计算结果的特征。 这种自底向上的递归方式时间复杂度为 $O(n)$(每个节点访问一次),空间复杂度为 $O(h)$(递归栈深度,h为树高)。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值