【学习笔记】二叉树LeetCode典型例题

107 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

看完本文你可以解决的问题有:

题目题型
104. 二叉树的最大深度 - 力扣(LeetCode)遍历二叉树/分解问题
543. 二叉树的直径 - 力扣(LeetCode)分解问题连带计算答案
102. 二叉树的层序遍历 - 力扣(LeetCode)层序遍历模板
515. 在每个树行中找最大值 - 力扣(LeetCode)层序遍历模板
  • 思路:

    二叉树的问题有两个主体思路:第一种是遍历一遍二叉树得出答案,第二种是通过分解问题计算出答案。

  • 理解前中后序:

    指的是几个不同的位置。

    前序:进入下一个节点之前。

    中序:遍历完左子树之后,即将要遍历子树之前。

    后序:即将离开当前节点之前。

  • 特殊的后序位置:

    二叉树的前序位置只能获取父节点传递过来的值,但是后序位置的代码不仅可以获取参数数据,还可以获取子树通过函数返回值传递回来的数据

  • 思考过程:

  1. 是否可以遍历一遍二叉树得到答案?如果可以,用一个 traverse 函数配合外部变量来实现。
  2. 是否可以定义一个递归函数,通过子问题(子树)的答案推导出原问题的答案?如果可以,写出这个递归函数的定义,并充分利用这个函数的返回值。
  3. 无论哪一种模式,都需要明白二叉树的每一节点需要做什么,需要在什么时候(前中后序)做?

LeetCode

  • leetcode 104

    思路一:通过遍历一遍二叉树得到答案。在刚进入节点时depth++,即将出节点时depth--,并且更新答案。

class Solution {
    int depth = 0;
    int ans = 0;
    public int maxDepth(TreeNode root) {
        traverse(root);
        return ans;
    }
    public void traverse(TreeNode root){
        if(root == null) return ;
        depth++;
        if(root.left == null && root.right == null){
            ans = Math.max(depth,ans);
        }
        traverse(root.left);
        traverse(root.right);
        depth--;
    }
}

思路二:通过分解问题的方式得到答案。

class Solution {
    //定义函数:返回返回子树的最大深度。
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        int leftmax = maxDepth(root.left);
        int rightmax = maxDepth(root.right);
        int ret = Math.max(leftmax , rightmax) + 1;
        return ret;
    }
}
  • leetcode 543

    分解问题法:定义函数Depth,返回子树的最大深度。其子树最大直径为Math.max(左子树最大深度+右子树最大深度,直径)

    class Solution {
        int max = 0;
        public int diameterOfBinaryTree(TreeNode root) {
            maxDepth(root);
            return max;
        }
        //函数定义:返回每一条子树的最大深度。
        public int maxDepth(TreeNode root){
            if(root == null) return 0;
            int leftDepth = maxDepth(root.left);
            int rightDepth = maxDepth(root.right);
            int myDepth = leftDepth + rightDepth;
            max = Math.max(max,myDepth);
            return 1 + Math.max(leftDepth,rightDepth);
        }
    }
    
  • leetcode 102

    二叉树的层序遍历。while循环遍历二叉树的行,for循环遍历二叉树的列。

    使用队列这一数据结构,先offerroot节点,之后使用for循环poll一行的节点。利用left和right指针继续offer节点。

    class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            List <List<Integer>> ans = new ArrayList<>();
            Queue <TreeNode> q = new LinkedList<>();
            if(root == null) return ans;
            q.offer(root);
            while(!q.isEmpty()){
                List <Integer> ret = new ArrayList<>();
                int size = q.size();
                for(int i = 0;i< size; i++){
                    TreeNode cur = q.poll();
                    ret.add(cur.val);
                    if(cur.left != null){
                        q.offer(cur.left);
                    }
                    if(cur.right != null){
                        q.offer(cur.right);
                    }
                }
                ans.add(ret);
            }
            return ans;
        }
    }
    
  • leetcode 515

    class Solution {
        public List<Integer> largestValues(TreeNode root) {
            List <Integer> ret = new ArrayList<>();
            Queue <TreeNode> q = new LinkedList<>();
            if(root == null) return ret;
            q.offer(root);
            while(!q.isEmpty()){
                int size = q.size();
                int max = Integer.MIN_VALUE;
                for(int i =0 ;i<size ; i++){
                    TreeNode cur = q.poll();
                    max = Math.max(cur.val,max);
                    if(cur.left != null){
                        q.offer(cur.left);
                    }
                    if(cur.right != null){
                        q.offer(cur.right);
                    }
                }
                ret.add(max);
            }
            return ret;
        }
    }
    

    \