算法刷题 - 二叉树(求二叉树深度专题)

87 阅读5分钟

算法刷题博客封面.png

题目 01 - 求二叉树的最大深度

原题链接

LeetCode 104 - 二叉树的最大深度

题目描述

给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

输入示例

思路 01 - 递归

本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的就是高度。

  • 二叉树节点的深度: 指从根节点到该节点的最长简单路径边的条数或者节点数目 (取决于深度从 0 开始还是从 1 开始)
  • 二叉树节点的高度: 指从该节点到叶子节点的最长简单路径边的条数或者节点数目 (却决于高度从 0 开始还是从 1 开始)

根节点的高度就是二叉树的最大深度

使用后序遍历实现

代码实现

class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        return getDepth(root);
    }

    //递归求最大深度;按照后序遍历的顺序: 左右根
    public int getDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        //递归得到左子树的最大深度
        int leftDepth = getDepth(root.left);
        //递归得到右子树的最大深度
        int rightDepth = getDepth(root.right);
        //树最大深度为左右子树中的最大深度 + 1
        int depth = 1 + Math.max(leftDepth, + rightDepth);
        return depth;
    }
}

执行结果

  • 时间复杂度: O(N)

  • 空间复杂度: O(N)

精简版本

class Solution {
    
    //递归求最大深度
    public int maxDepth(TreeNode root) {
        //如果当前节点为空
        if(root == null) return 0;
        //最大深度为左右子树的最大值 + 根节点本身的深度 (1)
        return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
    }
}

思路 02 - 前序遍历实现深度回溯递归

  • 前序遍历,根左右
  • 每层更新比较当前深度和记录的最大深度,使用 Math.max() 更新
  • 每层递归,如果左右子树其中有不为 null; 深度 + 1
  • 但是如果返回上一层递归,去上一层的递归查找其右子树的深度,需要将当前层的深度减小

代码实现

//起始深度标记为 1
class Solution {

    int result;

    public int maxDepth(TreeNode root) {
        if (root == null)
            return 0;
        int depth = 1; // 根节点默认深度为 1
        getDepth(root, depth);
        return result;
    }

    public void getDepth(TreeNode node, int depth) {
        // 递归返回条件
        if (node == null) {
            return;
        }
        // 更新最大深度
        result = Math.max(depth, result);
        // 若左子树不为空,更新当前深度
        if (node.left != null) {
            getDepth(node.left, depth + 1);
        }
        // 若右子树不为空,更新当前深度
        if (node.right != null) {
            getDepth(node.right, depth + 1);
        }
    }
}



//起始深度标记为 0

class Solution {

    int result;

    public int maxDepth(TreeNode root) {
        if (root == null)
            return 0;
        int depth = 0; // 起始深度为 0
        getDepth(root, depth);
        return result;
    }

    public void getDepth(TreeNode node, int depth) {
        // 递归返回条件
        if (node == null) {
            return;
        }
        // 当前层存在节点,更新最大深度
        depth++;
        result = Math.max(depth, result);
        // 若左子树不为空
        if (node.left != null) {
            getDepth(node.left, depth);
        }
        // 若右子树不为空
        if (node.right != null) {
            getDepth(node.right, depth);
        }
    }
}

执行结果

  • 间复杂度: O(N)

  • 空间复杂度: O(N)

思路03 - 迭代方式

使用层序遍历,最大深度就是二叉树的层数,和层序遍历的思路一致

优点:好理解

代码实现

class Solution {
    
    //递归求最大深度
    public int maxDepth(TreeNode root) {
        //如果当前节点为空
        if(root == null) return 0;
        //模拟队列
        Deque<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int depth = 0;
        while(!queue.isEmpty()) {
            int size = queue.size();
            depth++;
            for(int i = 0; i < size; i++) {
                TreeNode tmp = queue.pop();
                //如果左右子树不为空,需要更新最大高度
                if(tmp.left != null) queue.offer(tmp.left);
                if(tmp.right != null) queue.offer(tmp.right);
            }
        }
        return depth;
    }
}

执行结果

  • 时间复杂度: O(N)
  • 空间复杂度: O(N)

题目 02 - 求 N 叉树的最大深度

原题链接

LeetCode 559 - N 叉树的最大深度

题目描述

给定一个 N 叉树,找到其最大深度。

最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。

N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔。

输入示例

思路 - 递归实现

代码实现 - 传入起始深度为 0

class Solution {

    int ans; // 记录最大深度

    public int maxDepth(Node root) {
        if (root == null) {
            return 0;
        }
        int depth = 0;  //起始深度传入为 0
        getMaxDepth(root, depth);
        return ans;
    }

    public void getMaxDepth(Node node, int depth) {
        if (node == null) {
            return;
        }
        depth++; // 更新最大深度
        ans = Math.max(ans, depth);
        if (node.children != null && !node.children.isEmpty()) {
            // 如果子节点不为空,继续递归更新深度
            for (Node c : node.children) {
                getMaxDepth(c, depth);
            }
        }
    }
}

代码实现 - 传入起始深度为 1

class Solution {

    int ans; // 记录最大深度

    public int maxDepth(Node root) {
        if (root == null) {
            return 0;
        }
        int depth = 1;  //起始深度传入为 0
        getMaxDepth(root, depth);
        return ans;
    }

    public void getMaxDepth(Node node, int depth) {
        if (node == null) {
            return;
        }
        ans = Math.max(ans, depth);
        if (node.children != null && !node.children.isEmpty()) {
            // 如果子节点不为空,继续递归更新深度
            for (Node c : node.children) {
                //由于传入起始深度为 1, depth 已经表示当前层深度; 下一层更新为 depth + 1
                getMaxDepth(c, depth + 1);
            }
        }
    }
}

代码实现 - 递归

class Solution {
    public int maxDepth(Node root) {
        //检查输入
        if(root == null) {
            return 0;
        }
        //单层递归逻辑; 递归找到最大深度的节点
        int depth = 0;
        List<Node> children = root.children;
        for(Node n : children) {
            depth = Math.max(maxDepth(n), depth);
        }
        //从最大深度开始返回;最终加上根节点自身的深度 1
        return depth + 1;
    }
}

执行结果

时间复杂度: O(N)

空间复杂度: O(H)

思路 - 迭代

层序遍历思路。每一层遍历深度 + 1

代码实现

class Solution {
    public int maxDepth(Node root) {
        //检查输入
        if(root == null) {
            return 0;
        }
        //单层递归逻辑; 递归找到最大深度的节点
        Deque<Node> queue = new LinkedList<>();
        queue.offer(root);
        int depth = 0;  //记录最大深度
        while(!queue.isEmpty()) {
            int size = queue.size();
            depth++;
            //遍历所有含有children的子节点
            for(int i = 0; i < size; i++) {
                Node tmp = queue.pop();
                if(null != tmp.children) {
                    //加入其下的子节点
                    for(Node c : tmp.children) {
                        queue.offer(c);
                    }
                }
            }
        }
        return depth;
    }
}

执行结果

  • 时间复杂度: O(N)
  • 空间复杂度: O(N)

参考文献

代码随想录 - 求二叉树深度