速通Hot100-Day09——二叉树

【递归思想三部曲】

  • 确定递归函数的参数和返回值
  • 确定终止条件
  • 确定单层递归的逻辑

144. 二叉树的前序遍历

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    List<Integer> res = new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root == null) return res;
        preOrder(root);

        return res;
    }

    private void preOrder(TreeNode t) {
        if(t == null) return;

        res.add(t.val);
        if(t.left != null) preOrder(t.left);
        if(t.right != null) preOrder(t.right);
    }
}

94. 二叉树的中序遍历

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 */
class Solution {
    List<Integer> res = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        if(root == null) return res;
        inOrder(root);

        return res;
    }

    private void inOrder(TreeNode t) {
        if(t == null) return;

        if(t.left != null) inOrder(t.left);
        res.add(t.val);
        if(t.right != null) inOrder(t.right);
    }
}

145. 二叉树的后序遍历

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    List<Integer> res = new ArrayList<>();
    public List<Integer> postorderTraversal(TreeNode root) {
        if(root == null) return res;
        postOrder(root);
        return res;
    }

    private void postOrder(TreeNode t) {
        if(t == null) return;

        if(t.left != null) postOrder(t.left);
        if(t.right != null) postOrder(t.right);
        res.add(t.val);
    }
}

102. 二叉树的层序遍历

  • 时间复杂度:O(n),其中 n 为二叉树的节点个数,每个节点只会遍历一遍。
  • 空间复杂度:O(n)。队列中元素不超过 n 个。

只需要注意队列的实现以及使用即可。

这个是手写队列。

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        TreeNode[] q = new TreeNode[2010];
        int hh = 0,tt = -1;

        if(root == null) return res;
        q[++tt] = root;

        while(hh <= tt) {
            int len = tt - hh + 1;
            List<Integer> tmp = new ArrayList<>();
            while(len -- > 0) {
                TreeNode t = q[hh++];
                tmp.add(t.val);
                if(t.left != null) q[++tt] = t.left;
                if(t.right != null) q[++tt] = t.right;
            }
            res.add(tmp);
        }

        return res;
    }
}
java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if(root == null) return res;
        LinkedList<TreeNode> q = new LinkedList<>();
        q.offer(root);

        while(!q.isEmpty()) {
            int curSize = q.size();
            List<Integer> tmp = new ArrayList<>();
            while(curSize -- > 0) {
                TreeNode t = q.poll();
                tmp.add(t.val);
                if(t.left != null) q.offer(t.left);
                if(t.right != null) q.offer(t.right);
            }
            res.add(tmp);
        }

        return res;
    }
}

226. 翻转二叉树

交换指针,而不是交换节点值。

使用前序遍历,对其左右子树直接交换即可。

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null) return null;
        traversal(root);
        return root;
    }

    private void traversal(TreeNode cur) {
        if(cur == null) return;

        TreeNode tmp = new TreeNode();
        tmp = cur.left;
        cur.left = cur.right;
        cur.right = tmp;

        traversal(cur.left);
        traversal(cur.right);
    }
}

即使左右子树一个为空,那也可以交换。

所以这里层序遍历,一层一层进行交换也是可以的

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null) return null;

        LinkedList<TreeNode> q = new LinkedList<>();
        q.offer(root);

        while(!q.isEmpty()) {
            int curSize = q.size();
            while(curSize -- > 0) {
                TreeNode t = q.poll();
                if(t.left != null) q.offer(t.left);
                if(t.right != null) q.offer(t.right);
                TreeNode tmp = t.left;
                t.left = t.right;
                t.right = tmp;
            }
        }

        return root;
    }
}

101. 对称二叉树

  • 为什么要后续遍历?

我们要去判断一棵树是否对称,那么必然是要判断出该树的所有子树都是对称的;这也就意味着最后再去判断根节点:左 右 中。

compare逻辑中,是一个父节点与其左右孩子节点的逻辑。无非都空、左空、右空、值不相等、相等的情况

如果是前4种情况,可以直接判断结果;最后一种结果就要去看其子节点,就递归下去了:先看子节点最后传导父节点判断结果。

  • 其实是比较两个子树,是否可以翻转,这个说法成立不成立。

从理解上是这样,但就是对称。要比较左右子树是否完全对称,再去判断整棵树是否对称。

javascript 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
        return traversal(root.left, root.right);
    }

    private boolean traversal(TreeNode left, TreeNode right) {
        if(left == null && right == null) return true;
        if(left != null && right == null) return false;
        if(left == null && right != null) return false;
        if(left.val != right.val) return false;

        boolean out =  traversal(left.left, right.right);
        boolean in = traversal(left.right, right.left);
        return in && out;
    }
}

104. 二叉树的最大深度

就是求解一个树的高度问题,求最高的子树的高度。

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;

        return getDepth(root);
    }

    private int getDepth(TreeNode cur) {
        if(cur == null) return 0;

        int left = getDepth(cur.left);
        int right = getDepth(cur.right);
        return Math.max(left, right) + 1;
    }
}

使用层序求解,一共多少层,就是最大深度。

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        LinkedList<TreeNode> q = new LinkedList<>();
        q.offer(root);
        int res = 0;
        while(!q.isEmpty()) {
            int curSize = q.size();
            while(curSize-- > 0) {
                TreeNode t = q.poll();
                if(t.left != null) q.offer(t.left);
                if(t.right != null) q.offer(t.right);
            }
            res++; // 一层节点一计算
        }
        return res;
    }
}

111. 二叉树的最小深度

同理:就是求解一个树的高度问题,求最高的子树的高度。

那么这里认为,null 子树不算,计算另一个子树高度。

  • 为什么要这样计算?

null 节点不算是叶子节点,所以计算的是叶子节点的深度。

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if(root == null) return 0;
        return getDepth(root);
    }

    private int getDepth(TreeNode cur) {
        if(cur == null) return 0;

        int left = getDepth(cur.left);
        int right = getDepth(cur.right);
        if(cur.left == null) return right + 1;
        if(cur.right == null) return left + 1;
        return Math.min(left, right) + 1;
    }
}

层序遍历求解,不过特殊情况就是:这一层结束了,并且没有下一层了,所以必须 res++

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if(root == null) return 0;
        LinkedList<TreeNode> q = new LinkedList<>();
        q.offer(root);
        int res = 0;
        while(!q.isEmpty()) {
            int curSize = q.size();
            while(curSize-- > 0) {
                TreeNode t = q.poll();
                if(t.left == null && t.right == null) {
                    res++;
                    return res;
                }
                if(t.left != null) q.offer(t.left);
                if(t.right != null) q.offer(t.right);
            }
            res++; // 一层节点一计算
        }
        return res;
    }
}
相关推荐
土司大王13 小时前
LeetCode hot100——33.搜索旋转排序数组:Java 二分模板与 O(log n) 实现
数据结构·算法·leetcode
不穿鞋的懒羊羊13 小时前
STL容器
算法
huang57914713 小时前
多线程环境下的共享数据结构安全问题分析4
算法
地平线开发者14 小时前
模型部署|征程6 量化路线怎么选:PTQ 还是 QAT?
神经网络·算法·机器学习
辰辉创聚14 小时前
禽流感病毒分子基础:表面抗原与内部转录复合体的功能解析
ide·leetcode·rabbitmq·重组血凝素蛋白·甲型流感病毒核蛋白·禽流感单抗
不会就选b14 小时前
算法日常・每日刷题--<贪心>12
算法
小羊没烦恼!15 小时前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#
ysu_031415 小时前
08-二叉树遍历:四种方式详解
c语言·数据结构·算法·leetcode
咸鱼老弟15 小时前
Speculative Decoding(投机采样):大模型"先猜后验",生成速度翻倍
前端·算法·ai编程
荆棘鸟智能15 小时前
AI算法持续学习与迭代怎么做?从数据闭环到灰度发布的MLOps工程实践
人工智能·算法·架构·边缘计算