关于LeetCode中Maximum Depth of Binary Tree一题的理解

来源:互联网 发布:中国陶瓷出口数据 编辑:程序博客网 时间:2024/06/11 22:47

题目如下:

Given a binary tree, find its maximum depth.

The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

    题目内容也非常简单,给定一个二叉树的根结点,输出该二叉树的最大深度。然后题目解释了一下什么叫做“最大深度”,一个二叉树的最大深度是指根结点到叶子节点最长路径上的节点数量。

    最容易想到的解决方法是利用递归进行深度优先搜索,通过递归地比较一个节点左子树和右子树的最大深度,取其中较大值进行返回,自底向上地得到最后的结果。我第一次实现的方法如下:

<span style="font-size:14px;">public static int maxDepth(TreeNode root) {        if (root == null){            return 0;        }else if(root.right == null && root.left == null){            return 1;        }else{            if(maxDepth(root.right)>=maxDepth(root.left)){                return maxDepth(root.right)+1;            }else{                return maxDepth(root.left)+1;            }        }    }</span>
    这个解法思路是和上面的陈述一模一样的,但是最终结果却是超时了。哪里出了问题呢?我们先看下面已经Accepted的解法:

<span style="font-size:14px;">public int maxDepth(TreeNode root) {        if (root == null){            return 0;        }else if(root.right == null && root.left == null){            return 1;        }else{            int rightMax = maxDepth(root.right) + 1;            int leftMax = maxDepth(root.left) + 1;            if(rightMax-leftMax>=0){                return rightMax;            }else{                return leftMax;            }        }    }</span>
    这两种解法唯一的不同是我把一个节点左子树和右子树的最大深度单独赋值给了两个变量rightMax和leftMax。而在第一种解法中我并没有这样做,而是在比较后又重新计算了一遍左子树和右子树的最大深度,所以超时的原因就在于这个多出来的左子树(或右子树)最大深度递归时间。

再看一下在讨论区使用同样思路的答案:

<span style="font-size:14px;">public int maxDepth(TreeNode root) {        return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;    }</span>

    这个答案省略了上面return 1情况的判断,因为确实也没有判断的必要。然后就是使用了java中Math包自带的函数来找出两个数的最大值,这个也没什么可说的。最后的话就是利用了一下三元表达式,如果根结点root为null的话就返回0,否则就返回(其左右子树中最大深度较大的那一个+1)。

    评论区中还有一种方法是使用循环的方式,在这种方式中使用了HashMap和Stack,还是挺有意思的,代码实现如下:

<span style="font-size:14px;">public int maxDepth(TreeNode root) {        if (root == null) {            return 0;        }        Map<TreeNode, Integer> depthMap = new HashMap<>();        depthMap.put(root, 1);        int maxDepth = 1;        Stack<TreeNode> stack = new Stack<>();        stack.push(root);        while (!stack.isEmpty()) {            root = stack.pop();            int depth = depthMap.get(root);            maxDepth = Math.max(maxDepth, depthMap.get(root));            if (root.right != null) {                depthMap.put(root.right, depth + 1);                stack.push(root.right);            }            if (root.left != null) {                depthMap.put(root.left, depth + 1);                stack.push(root.left);            }            depthMap.remove(root);        }        return maxDepth;    }</span>
    首先弄一个HashMap,里面存放的是二叉树中的每个节点和其对应的层数(根结点是第一层,根结点的子节点是第二层,根结点的子节点的子节点是第三层以此类推),并先将根结点root放置到该HashMap中,其层数为1。然后声明一个栈(Stack)这个是用来进行循环遍历的。如何进行循环遍历呢?首先pop出一个节点,第一次pop的必定是根结点,然后将其左右子节点分别压入栈中。这时根结点root已经不在栈中了,说明root节点已经被遍历过了。下面开始遍历其左右子节点,用同样的方法把左子节点的pop出去,然后把左子节点的左右子节点压入栈中,以此类推。这样就会遍历到所有的子节点,且遍历完成时,栈中没有任何节点,因为这些节点都被pop出去了。

    这个方法的亮点主要在于用Stack来实现了循环遍历,挺有意思的。在循环里面如何计算最大深度就不再赘述了,看代码马上就能明白。

    总结一下就是妈妈再也不用担心我只会用递归的方法遍历二叉树了,我也会用通过Stack进行循环的方式遍历二叉树了!




1 0