hot100——二叉树

二叉树的中序遍历

94. 二叉树的中序遍历 - 力扣(LeetCode)

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

示例 1:

复制代码
输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

复制代码
输入:root = []
输出:[]

示例 3:

复制代码
输入:root = [1]
输出:[1]

解法及思路

三种遍历顺序:

复制代码
前序:根 → 左 → 右
中序:左 → 根 → 右
后序:左 → 右 → 根

中序遍历:先遍历左子树,再访问根,最后遍历右子树。

递归(最简洁)

二叉树:

复制代码
    1
   / \
  2   3
 / \
4   5

调用 inorder(1, result):

复制代码
inorder(1)
  ├─ inorder(2)
  │   ├─ inorder(4)
  │   │   ├─ inorder(null) → 返回
  │   │   ├─ result.add(4) → result=[4]
  │   │   └─ inorder(null) → 返回
  │   ├─ result.add(2) → result=[4, 2]
  │   └─ inorder(5)
  │       ├─ inorder(null) → 返回
  │       ├─ result.add(5) → result=[4, 2, 5]
  │       └─ inorder(null) → 返回
  ├─ result.add(1) → result=[4, 2, 5, 1]
  └─ inorder(3)
      ├─ inorder(null) → 返回
      ├─ result.add(3) → result=[4, 2, 5, 1, 3]
      └─ inorder(null) → 返回

最终:result = [4, 2, 5, 1, 3]
java 复制代码
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        inorder(root, result);
        return result;
    }
    
    private void inorder(TreeNode node, List<Integer> result) {
        if (node == null) return;
        inorder(node.left, result);   // 左
        result.add(node.val);         // 根
        inorder(node.right, result);  // 右
    }
}

二叉树的最大深度

104. 二叉树的最大深度 - 力扣(LeetCode)

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

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

示例 1:

复制代码
输入:root = [3,9,20,null,null,15,7]
输出:3

示例 2:

复制代码
输入:root = [1,null,2]
输出:2

解法及思路

递归

最大深度 = 1 + max(左子树深度, 右子树深度)

复制代码
depth(root) = 1 + max(depth(root.left), depth(root.right))

终止条件:root == null,返回 0

二叉树:

复制代码
    3
   / \
  9  20
    /  \
   15   7

递归计算:

复制代码
depth(3)
  = 1 + max(depth(9), depth(20))
  = 1 + max(1, depth(20))
  = 1 + max(1, 1 + max(depth(15), depth(7)))
  = 1 + max(1, 1 + max(1, 1))
  = 1 + max(1, 2)
  = 1 + 2
  = 3

翻转二叉树

226. 翻转二叉树 - 力扣(LeetCode)

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

复制代码
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

复制代码
输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

复制代码
输入:root = []
输出:[]

解法及思路

递归

对每个节点,交换它的左右子树。

复制代码
1. 终止条件:root == null,返回 null
2. 交换 root.left 和 root.right
3. 递归翻转左子树
4. 递归翻转右子树
5. 返回 root

二叉树:

复制代码
    4
   / \
  2   7
 / \ / \
1  3 6  9

递归翻转:

复制代码
第1步:交换4的左右子树
    4
   / \
  7   2
 / \ / \
6  9 1  3

第2步:交换7的左右子树
    4
   / \
  7   2
 / \ / \
9  6 1  3

第3步:交换2的左右子树
    4
   / \
  7   2
 / \ / \
9  6 3  1

结果:
    4
   / \
  7   2
 / \ / \
9  6 3  1
java 复制代码
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null) return null;
        //交换左右子树
        TreeNode temp=root.right;
        root.right=root.left;
        root.left=temp;
        //递归翻转左右子树
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}

对称二叉树

101. 对称二叉树 - 力扣(LeetCode)

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:

复制代码
输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:

复制代码
输入:root = [1,2,2,null,3,null,3]
输出:false

解法及思路

递归比较左右子树

对称的条件:

复制代码
左子树的左 和 右子树的右 对称
左子树的右 和 右子树的左 对称

即:

复制代码
compare(left, right):
  1. left 和 right 都为空 → true
  2. left 或 right 一个为空 → false
  3. left.val != right.val → false
  4. 递归比较:
     compare(left.left, right.right)
     compare(left.right, right.left)

对称的树:

复制代码
    1
   / \
  2   2
 / \ / \
3  4 4  3

比较:
  2 和 2:相等 ✅
  2.left=3 和 2.right=3:相等 ✅
  2.right=4 和 2.left=4:相等 ✅
  3.left=null 和 3.right=null:相等 ✅
  4.left=null 和 4.right=null:相等 ✅
  ...

结果:true

不对称的树:

复制代码
    1
   / \
  2   2
   \   \
   3    3

比较:
  2 和 2:相等 ✅
  2.left=null 和 2.right=3:一个空一个非空 ❌

结果:false
java 复制代码
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null) return true;
        return compare(root.left,root.right);
    }
    public boolean compare(TreeNode left,TreeNode right){
        //都为空
        if(left==null && right==null) return true;
        //一个为空
        if(left==null || right==null) return false;
        //值不相等
        if(left.val!=right.val) return false;
        //递归比较
        return compare(left.left,right.right) && compare(left.right,right.left);
    }
}

二叉树的直径

543. 二叉树的直径 - 力扣(LeetCode)

给你一棵二叉树的根节点,返回该树的 直径 。

二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。

两节点之间路径的 长度 由它们之间边数表示。

示例 1:

复制代码
输入:root = [1,2,3,4,5]
输出:3
解释:3 ,取路径 [4,2,1,3] 或 [5,2,1,3] 的长度。

示例 2:

复制代码
输入:root = [1,2]
输出:1

解法及思路

递归计算深度

关键:直径 = 左子树深度 + 右子树深度

复制代码
对于每个节点:
  左子树深度 = depth(left)
  右子树深度 = depth(right)
  经过该节点的直径 = 左深度 + 右深度
  全局直径 = max(所有节点的直径)

二叉树:

复制代码
    1
   / \
  2   3
 / \
4   5

计算每个节点的直径:

复制代码
节点4:左深度0 + 右深度0 = 0
节点5:左深度0 + 右深度0 = 0
节点2:左深度1 + 右深度1 = 2
节点3:左深度0 + 右深度0 = 0
节点1:左深度2 + 右深度1 = 3

最大直径 = 3
java 复制代码
class Solution {
    private int maxlength=0;

    public int diameterOfBinaryTree(TreeNode root) {
        depth(root);
        return maxlength;
    }
    private int depth(TreeNode node){
        if(node==null) return 0;
        int leftlength=depth(node.left);
        int rigthlength=depth(node.right);
        int length=leftlength+rigthlength;
        // 更新最大直径
        maxlength=Math.max(length,maxlength);
        // 返回当前节点的深度
        return 1+Math.max(leftlength,rigthlength);
    }
}

二叉树的层序遍历

102. 二叉树的层序遍历 - 力扣(LeetCode)

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

复制代码
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

复制代码
输入:root = [1]
输出:[[1]]

示例 3:

复制代码
输入:root = []
输出:[]

解法及思路

BFS + 队列

用队列逐层遍历:

复制代码
1. 根节点入队
2. 每次处理当前层的所有节点
3. 把下一层的节点入队
4. 重复直到队列为空

二叉树:

复制代码
    3
   / \
  9  20
    /  \
   15   7
复制代码
初始:queue = [3]

第1层:
  处理3,把9和20入队
  result = [[3]]
  queue = [9, 20]

第2层:
  处理9,无子节点
  处理20,把15和7入队
  result = [[3], [9, 20]]
  queue = [15, 7]

第3层:
  处理15,无子节点
  处理7,无子节点
  result = [[3], [9, 20], [15, 7]]
  queue = []

结束
java 复制代码
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result=new ArrayList<>();
        if(root==null) return result;
        
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);

        while(!queue.isEmpty()){
            int size=queue.size();// 当前层的节点数
            List<Integer> level=new ArrayList<>();

            // 处理当前层的所有节点
            for(int i=0;i<size;i++){
                TreeNode node=queue.poll();
                level.add(node.val);

                // 下一层入队
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
            }
            result.add(level);
        }
        return result;

    }
}

二叉树的最近公共祖先

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:"对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。"

示例 1:

复制代码
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 `5 `和节点 `1 `的最近公共祖先是节点 `3 。`

示例 2:

复制代码
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 `5 `和节点 `4 `的最近公共祖先是节点 `5 。`因为根据定义最近公共祖先节点可以为节点本身。

示例 3:

复制代码
输入:root = [1,2], p = 1, q = 2
输出:1

解法及思路

递归

对于每个节点,判断 p 和 q 是否在它的子树中。

复制代码
1. 如果 node 是 p 或 q,返回 node
2. 递归左子树,得到 left
3. 递归右子树,得到 right
4. 如果 left 和 right 都不为空,说明 p 和 q 分别在两边,node 就是 LCA
5. 如果 left 为空,返回 right
6. 如果 right 为空,返回 left

二叉树:

复制代码
        3
       / \
      5   1
     / \ / \
    6  2 0  8
      / \
     7   4

情况1:p=5, q=1

复制代码
递归到3:
  左子树返回5(找到p)
  右子树返回1(找到q)
  left 和 right 都不为空
  → 3就是LCA ✅

情况2:p=5, q=4

复制代码
递归到3:
  左子树递归到5:
    左子树递归到6:返回null
    右子树递归到2:
      左子树递归到7:返回null
      右子树递归到4:返回4(找到q)
      → 2的右子树返回4,左子树null
      → 返回4
    → 5的左子树null,右子树返回4
    → 5本身就是p,返回5
  → 3的左子树返回5
  右子树递归到1:
    返回null(p和q都不在)
  → 3的左子树返回5,右子树null
  → 返回5
  → 5就是LCA ✅
java 复制代码
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //终止条件
        if(root==null||root==p||root==q){
            return root;
        }
        //递归左右子树
        TreeNode left=lowestCommonAncestor(root.left,p,q);
        TreeNode right=lowestCommonAncestor(root.right,p,q);
        //左右都不为空,说明pq分别在两边
        if(left!=null&&right!=null){
            return root;
        }
        //返回非空的那个
        return (left!=null)?left:right;
    }
}

验证二叉搜索树

98. 验证二叉搜索树 - 力扣(LeetCode)

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含严格小于当前节点的数。
  • 节点的右子树只包含 严格大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

复制代码
输入:root = [2,1,3]
输出:true

示例 2:

复制代码
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

解法及思路

中序遍历

BST 的中序遍历是严格递增的。

复制代码
中序遍历:左 → 根 → 右
如果是BST,结果一定是升序

所以:中序遍历,检查是否严格递增。

BST:

复制代码
    2
   / \
  1   3

中序遍历:[1, 2, 3] → 递增 ✅

非BST:

复制代码
    5
   / \
  1   4
     / \
    3   6

中序遍历:[1, 5, 3, 4, 6] → 3 < 5,不递增 ❌
java 复制代码
class Solution {
    private long prev = Long.MIN_VALUE;  // 记录前一个节点的值
    
    public boolean isValidBST(TreeNode root) {
        if(root==null) return true;
        //左
        if (!isValidBST(root.left)) return false;

        // 根:检查是否 > prev
        if (root.val <= prev) return false;
        prev = root.val;
        
        // 右
        return isValidBST(root.right);
    }
}
相关推荐
打工仔折腾 AI1 小时前
System Prompt 替代 Few-shot:用规则约束大模型输出的省钱实践
java·人工智能·python·spring·langchain·prompt·ai agent 实战
CarIise1 小时前
Java实训阶段查漏补缺复习笔记1
java·开发语言·笔记
Code_Solitude2 小时前
c语言:二分法的完整补充
c语言·开发语言·算法
一切皆是因缘际会2 小时前
掌控信息论:同源星际通信基础理论
人工智能·算法·ai
vx-程序开发2 小时前
【计算机毕设】51300童装超市管理系统的设计与实现
java·vue.js·spring boot·源码·课程设计·毕设·大作业
ym hyd 1113 小时前
题库建立与考试系统源码 Java+SpringBoot+Vue3 前后分离
java·开发语言·vue.js·spring boot·毕设
risc1234563 小时前
什么是码点?
java
List<String> error_P3 小时前
freertos数据结构--链表
数据结构·链表
JavaPub-rodert3 小时前
公共 Docker 镜像源总失效?用 Harbor Proxy Cache 自建 Docker Hub 镜像缓存
java·缓存·docker