美文网首页
二叉树深度计算

二叉树深度计算

作者: 一剑飘虹刹九洲 | 来源:发表于2019-03-10 16:20 被阅读0次

    今天面试,被问到了二叉树的深度计算问题。
    一听到这个问题,第一反应是大学被写烂了的基本数据结构问题。
    然而我已经毕业3年,没写算法很久,手都生了。但是呢,不能说生了就只对面试官说思路吧,于是还是不假思索的立马拿起笔,写了起来,毕竟这是一个基本的数据结构题目。
    首先立马写了一个二叉树结构。

    public class BinaryTree{
            BinaryTree lChild, rChild;
            int value;
        }
    

    一写出来,立马有了感觉。顺势写了计算方法

    public int computeTreeDepth(BinaryTree binaryTree){
            if(binaryTree.lChild == null && binaryTree.rChild == null){
                return 1;
            }
            int lDepth = computeTreeDepth(binaryTree.lChild);
            int rDepth = computeTreeDepth(binaryTree.rChild);
            return Math.max(lDepth, rDepth);
        }
    

    然后就给面试官看了。
    面试官问我有感觉哪里不对吗?哎,只怪我太久没写算法题了,连这个基本的深度计算,都出现简单失误。更可气的是在当时的紧张环境下,我竟然没有发现哪里问题。后来经过面试官提醒,也终于改了过来。

        public int computeTreeDepth(BinaryTree binaryTree){
            if(binaryTree == null){
                return 0;
            }
            if(binaryTree.lChild == null && binaryTree.rChild == null){
                return 1;
            }
            int lDepth = computeTreeDepth(binaryTree.lChild) + 1;
            int rDepth = computeTreeDepth(binaryTree.rChild) + 1;
            return Math.max(lDepth, rDepth);
        }
    

    此时我的心里一万个对自己无语,竟然在面试的时候出现这么大的失误(不过也只怪我平常自从毕业就很少去深入写算法题了,以后一定要注意)
    这个时候,面试官说这是递归实现,写一下非递归实现。
    当时心里无语的我顿时一塞,非递归实现,然后一想,也简单。然后就屁颠屁颠的开始写起来。写着写着我发现,情况似乎不是我想的这么简单。随着时间的深入,我的心里变得异常紧张,结果硬是在那几分钟没想出来。此刻真是深深的鄙视自己,无论是什么原因让我当时的大脑短路了,终究的结果是我没写出来非递归实现。之后面试官委婉的叫我下去在思考这个问题吧。

    总结一下:
    问题:自己当时太想着展现自己,导致自己的思路太过紧凑反而限制了我的思维,导致这个简单的问题也写出漏洞,甚至连非递归实现最后没编写出来。
    对自己的思考:
    1.作为程序猿,平常还是要多锻炼自己的算法编写习惯,多去思考。只有这样才可以在面试中对算法题有一个较好的把控。
    2.面试的时候心态要放平稳,不能心浮气躁,导致自己出现各种临时小问题。因为对方只会看结果。

    回来了,自己重新写了一遍二叉树的深度计算实现,果然很简单。记录一下吧,就当是自己前进的路上的一个绊脚石,也希望自己在每一次总结之后能进步自己。
    多思考,多学习,放平心态,去面对每一个新技术,新思维。

    下面贴代码,以及思路
    二叉树深度计算的递归实现:

        public int computeTreeDepth(BinaryTree binaryTree){
            if(binaryTree == null){
                return 0;
            }
            return Math.max(computeTreeDepth(binaryTree.lChild), computeTreeDepth(binaryTree.rChild)) + 1;
        }
    

    二叉树深度计算的非递归实现:
    首先想到是直接遍历,如果是直接遍历那自然就有两种思路,广度优先和深度优先。
    先说广度优先,因为是遍历下一层意味着上一层都已遍历,先进先出,采用队列实现:

        public int computeTreeDepth(BinaryTree binaryTree){
            //实例化队列
            Queue<BinaryTree> mVisitList = new LinkedList<>();
            BinaryTree tmp;
            int depth = 0, lengthTmp;
            if(binaryTree == null){
                //根为空,直接返回0
                return 0;
            }
            //将根加入队列
            mVisitList.offer(binaryTree);
            while (!mVisitList.isEmpty()){
                //只要队列不为空,说明新的一层数据不为空,且已经加到队列,深度+1
                depth ++;
                //遍历该层到所有数据,将他们出队,并附带把所有下一层到数据都加进来(如果有的话)
                lengthTmp = mVisitList.size();
                while (lengthTmp -- > 0){
                    tmp = mVisitList.poll();
                    if(tmp.lChild != null){
                        mVisitList.offer(tmp.lChild);
                    }
                    if(tmp.rChild != null){
                        mVisitList.offer(tmp.rChild);
                    }
                }
            }
            return depth;
        }
    

    然后深度优先,因为是深度遍历那肯定是先进后出,采用栈实现,然后遍历思路是先遍历当前节点的左子树,没有左子树到情况在遍历右子树:

        public int computeTreeDepth(BinaryTree binaryTree){
            //实例化栈
            Stack<BinaryTree> mVisitList = new Stack<>();
            BinaryTree tmp = binaryTree;
            int depth = 0;//遍历过程中到最大深度
            while (tmp != null){
                if(tmp.lChild != null || tmp.rChild != null){
                    //如果有子树,将当前节点入栈,且更新最大深度
                    mVisitList.push(tmp);
                    depth = Math.max(depth, mVisitList.size());
                    //因为是左子树优先,所以深度遍历下一个子节点的时候,优先左子树
                    tmp = tmp.lChild != null ? tmp.lChild : tmp.rChild;
                    continue;
                }
                //当前节点没有子树,直接更新最大深度(访问到当前节点到深度是栈的深度+1)
                depth = Math.max(depth, mVisitList.size() + 1);
                //此时回溯去找右子树
                while (!mVisitList.isEmpty()){
                    if(mVisitList.peek().rChild != null){
                        //如果栈顶节点的右子树不为空,访问右子树
                        //访问的时候注意,如果栈顶节点的右子树等于当前正在访问的节点,应该置空避免没必要的循环
                        tmp = mVisitList.peek().rChild == tmp ? null : mVisitList.peek().rChild;
                        break;
                    }
                    //说明当前栈顶节点的右子树为空,直接出栈,继续回溯
                    // 且要更新当前节点,用于记录当前正在回溯的节点,避免死循环回溯
                    tmp = mVisitList.pop();
                }
            }
            return depth;
        }
    

    好了,上面就是二叉树的实现,自己写了几个测试用例没出现问题。但是不能保证完全没问题,有问题的话或者可以优化的欢迎留言交流,一起学习进步。
    最后,希望我的总结也可以让你在接下来的工作中或者学业上也有所帮助。

    相关文章

      网友评论

          本文标题:二叉树深度计算

          本文链接:https://www.haomeiwen.com/subject/xyztmxtx.html