Leetcode 刷题日记 2021.2.14 二叉树的深度

Leetcode 刷题日记

2021.2.14

题目链接:

https://leetcode-cn.com/problems/er-cha-shu-de-shen-du-lcof/submissions/

问题描述:

输入二叉树的根节点,返回其深度
Leetcode 刷题日记 2021.2.14 二叉树的深度_第1张图片

解答1:

非递归深度优先搜索

代码:

public class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        //若根节点为空,则深度为0,否则执行下面的代码
        LinkedList<TreeNode> stack = new LinkedList<>();
        stack.push(root);
        int depth = 0;
        while(!stack.isEmpty()){         
            TreeNode oldPeek = stack.peek();
            if(oldPeek.left != null) {
                stack.push(oldPeek.left);
                oldPeek.left = null;
            }
            else if(oldPeek.right != null) {
                stack.push(oldPeek.right);
                oldPeek.right = null;
            }
            else{
                depth = Math.max(depth, stack.size());
                stack.pop();
            }
        }
        return depth;
    }
}

分析:

时间复杂度:O(n)
空间复杂度:O(n)

运行结果:

Leetcode 刷题日记 2021.2.14 二叉树的深度_第2张图片

评注:

深度优先搜索的基本原理:
1.记号约定:从一个节点(记为F)第一次到达下一个节点(记为S),则把F标记为S的上一节点。
2.基本操作:
①若S即为搜索的目标,则返回S;
②否则,若从S还有通向其他节点(即,除F外的节点)的路径,则选择某一路径进入下一节点;
③否则,若从S只有通向F的路径,则返回到F,并把从F到S的路径擦除,然后判断是否有F通向其他节点(即,除F的上一节点外的节点)的路径,若有,则进入②,否则进入③。

深度优先搜索可以通过维护一个栈来实现:
1.首先,把根节点压入栈中,使栈顶节点不为null。
2.然后,构建循环
(1)若栈顶节点(设为P)有左孩子(左孩子域不为null),则将左孩子压入栈中,使左孩子成为新的栈顶,同时把P的左孩子域设为null。
(2)否则,若栈顶节点有右孩子(右孩子域不为null),则将右孩子压入栈中,使右孩子成为新的栈顶,同时把P的右孩子域设为null。
(3)否则,该节点必为叶子节点或其左右子树都被遍历过,此时栈的元素个数即为该节点的深度,记录深度后将其弹出。

所有记录的深度的最大值即为树的深度

题外话:这实际涉及到对树的遍历。树的遍历方式有两大类,一类是基于深度优先的先序、中序和后序遍历;另一类是基于广度优先的层次遍历。
前者可以使用栈来实现(如本解答),后者可以用队列来实现(如下一解答)。

解答2:

非递归广度优先搜索(层次遍历)

代码:

public class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        int depth = 1;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.addFirst(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode oldFirst = queue.removeFirst();
                if(oldFirst.left != null) queue.addLast(oldFirst.left);
                if(oldFirst.right != null) queue.addLast(oldFirst.right);
            }
            depth ++;
        }
        return depth;
    }
}

分析:

时间复杂度:O(n)
空间复杂度:O(n)

运行结果:

Leetcode 刷题日记 2021.2.14 二叉树的深度_第3张图片

评注:

与基于栈的深度优先搜索相对应,本题也可使用基于队列的广度优先搜索解答。具体思路可以类比深度优先。由于这里是一层一层地遍历,所以在while循环里面嵌套了一个for循环来对每一层的节点进行遍历。

解答3:

递归(本质是深度优先)

代码:

public class Solution {
    public int maxDepth(TreeNode root) {
         if(root == null) return 0;
         else if(root.left == null && root.right == null) return 1;
         else if(root.left != null && root.right == null) return maxDepth(root.left) + 1;
         else if(root.left == null && root.right != null) return maxDepth(root.right) + 1;
         else return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
    }
}

分析:

时间复杂度:O(n)
空间复杂度:O(n)

运行结果:

Leetcode 刷题日记 2021.2.14 二叉树的深度_第4张图片

评注:

递归是最快的解答。虽然本题给出的三种解答的时间复杂度相同,但是由于递归所需要的操作少于前两种,并且由于本题数据量不大,调用方法所消耗的时间可以忽略,所以递归成为了最快的实现方式。

你可能感兴趣的:(Leetcode刷题笔记,leetcode,算法,数据结构,二叉树,队列)