parasafi
parasafi
发布于 2026-09-20 / 10 阅读
0
0

LeetCodeHot100-二叉树部分题目

25.二叉树中序遍历

示例 1:

img
输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

题解:

class Solution {

  public List<Integer> inorderTraversal(TreeNode root) {
   List<Integer> res = new ArrayList();
   inorder(root,res);
   return res;
  }

  public void inorder(TreeNode root,List<Integer> res){
   if(root == null){
     return;
   }
   //这里灵活调整三行代码顺序就可以决定是前,中,后三种遍历顺序(前:将res.add(root.val)放到最前面,后:将res.add(root.val)放到最后面)
   inorder(root.left,res);
   res.add(root.val);
   inorder(root.right,res);
  }
}

26二叉树的最大深度

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

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

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:3

示例 2:

输入:root = [1,null,2]
输出:2

题解:

class Solution {

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

27.翻转二叉树

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

示例 1:

img
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

img
输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

输入:root = []
输出:[]

题解:

class Solution {

  public TreeNode invertTree(TreeNode root) {
    if(root == null){
      return null;
    }
    TreeNode left = invertTree(root.left);
    TreeNode right = invertTree(root.right);
    root.left = right;
    root.right = left;
    return root;
  }
}

28.对称二叉树

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

示例 1:

img
输入:root = [1,2,2,3,4,4,3]
输出:true

题解:

class Solution {

  public boolean isSymmetric(TreeNode root) {
   return check(root.left,root.right);
  }
  public boolean check(TreeNode p,TreeNode q){
   if(p == null && q== null){
     return true;
   }
   if(p == null || q == null){
     return false;
   }
   return p.val == q.val && check(p.left,q.right) && check(p.right,q.left);
  }
}

29.二叉树的半径

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

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

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

示例 1:

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

示例 2:

输入:root = [1,2]
输出:1

核心思想:

找到左右子树深度之和最大值

题解:

class Solution {
​
  int ans;
​
  public int diameterOfBinaryTree(TreeNode root) {
    ans = 1;
    depth(root);
    return ans - 1;
  }
  public int depth(TreeNode root){
    if(root == null){
      return 0;
    }
    int L = depth(root.left);
    int R = depth(root.right);
    ans = Math.max(ans,L + R + 1);
    return Math.max(L,R) + 1;
  }
}

30.二叉树层序遍历

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

示例 1:

img
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

核心思想:

使用队列来对存储处理每一个节点保证按顺序处理节点,其次通过队列当前有的元素来判断当前层数有几个节点要处理。

题解:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ans = new ArrayList();
        if(root == null){
            return ans;
        }
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            List<Integer> level = new ArrayList();
            int currentLevel = queue.size();
            for(int i = 1; i <= currentLevel;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);
                }
            }
            ans.add(level);
        }
        return ans;
    }
}

31.将有序数组转为二叉树

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。

示例 1:

img
输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

img
输入:nums = [1,3]
输出:[3,1]
解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。

这道题相对简单,方法有很多种,这里就以中序遍历的其中一种方式来做。

题解:

通过中序遍历,选择中间位置左边的数字作为根节点

class Solution {

  public TreeNode sortedArrayToBST(int[] nums) {
     return helper(nums,0,nums.length - 1);
  }

  public TreeNode helper(int[] nums,int left,int right){
     if(left > right){
       return null;
     }
     int mid = (left + right + 1) / 2;
     TreeNode root = new TreeNode(nums[mid]);
     root.left = helper(nums,left,mid - 1);
     root.right = helper(nums,mid + 1,right);
     return root;
  }
}

32.验证二叉搜索树

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

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

  • 节点的左子树只包含 严格小于 当前节点的数。

  • 节点的右子树只包含 严格大于 当前节点的数。

  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

img
输入:root = [2,1,3]
输出:true

示例 2:

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

题解:

class Solution {

  public boolean isValidBST(TreeNode root) {
     return isValidBST(root,Long.MIN_VALUE,Long.MAX_VALUE);
  }
  public boolean isValidBST(TreeNode node,long lower,long higher){

     if(node == null){
       return true;
     }
     if(node.val <= lower || node.val >= higher){
       return false;
     }
     return isValidBST(node.left,lower,node.val) && isValidBST(node.right,node.val,higher);
  }
}

33.二叉搜索树查询倒数K个小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 小的元素(k 从 1 开始计数)。

示例 1:

img
输入:root = [3,1,4,null,2], k = 1
输出:1

示例 2:

img
输入:root = [5,3,6,2,4,null,null,1], k = 3
输出:3

题解:

这题主要结合二叉搜索树的特点,因为我们要找的是偏小的一边,所以我们优先搜索左子树,将左子树的节点塞到栈里面,然后再k次出栈就可以找到第k小的节点

class Solution {
​
  public int kthSmallest(TreeNode root, int k) {
​
      Deque<TreeNode> stack = new ArrayDeque<>();
      while(root != null || !stack.isEmpty()){
        //优先搜索左子树
        while(root != null){
          stack.push(root);
          root = root.left;
        }
        //出栈k次就能拿到第k小的节点
        root = stack.pop();
        --k;
        //k==0则找到了直接中断
        if(k == 0){
          break;
        }
        //当最左端的左子树都找完没找到,那么就从子树节点的右子树节点开始,但后续搜索还是优先左子树搜索
        root = root.right;
      }
      return root.val;
  }
}

34.二叉树右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例 1:

输入:root = [1,2,3,null,5,null,4]

输出:[1,3,4]

解释:

img

示例 2:

输入:root = [1,2,3,4,null,null,null,5]

输出:[1,3,4,5]

解释:

img

示例 3:

输入:root = [1,null,3]

输出:[1,3]

示例 4:

输入:root = []

输出:[]

题解:

这题我们用层序遍历即可,只往res数组添加每层的最后一个节点值即可。

class Solution {
​
  public List<Integer> rightSideView(TreeNode root) {
​
       List<Integer> ans = new ArrayList();
​
       if(root == null){
         return ans;
       }
       Deque<TreeNode> queue = new LinkedList<>();
       queue.offer(root);
       while(!queue.isEmpty()){
         int size = queue.size();
         while(size > 0){
           TreeNode cur = queue.poll();
           size--;
           //只往结果数组添加最后一个元素,正常层序遍历没有这个if条件直接添加
           if(size == 0){
             ans.add(cur.val);
           }
           if(cur.left != null){
             queue.offer(cur.left);
           }
           if(cur.right != null){
             queue.offer(cur.right);
           }
         }
       }
       return ans;
  }
}

35.二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。

  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

示例 1:

img
输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [0]
输出:[0]

题解:

这题用先序遍历把节点存到list里面,然后通过遍历list访问节点来改变节点的指针,for循环 i 初始记得设为1

class Solution {
​
  public void flatten(TreeNode root) {
        List<TreeNode> list = new ArrayList();
        preorder(root,list);
        int size = list.size();
        //i索引指向当前子树的左节点,i-1就是根节点
        for(int i = 1;i < size;i++){
          TreeNode prev = list.get(i - 1), curr = list.get(i);
          prev.left = null;
          prev.right = curr;
        }
  }
​
  public void preorder(TreeNode root,List<TreeNode> list){
        if(root != null){
          list.add(root);
          preorder(root.left,list);
          preorder(root.right,list);
        }
  }
}

36.从先序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

img
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

题解:

做这题要先找到两个遍历的特性

  • 前序遍历:根 → 左子树 → 右子树,所以 preorder[0] 一定是整棵树的根。

  • 中序遍历:左子树 → 根 → 右子树,所以只要在中序数组中找到根的位置,就能把左、右子树的中序区间分开。

用一个指针 inorderIndex 指向中序遍历中「当前应该被匹配」的位置。

遍历前序数组 preorder,依次处理每个节点:

  1. 如果栈顶节点的值 ≠ inorder[inorderIndex]

    • 说明当前前序节点是栈顶节点的左孩子。

    • 因为前序是「根→左」,只要还没走到中序里的根,就一直在往左走。

    • 于是 node.left = new TreeNode(preorderVal),并压栈。

  2. 如果栈顶节点的值 == inorder[inorderIndex]

    • 说明栈顶这个节点已经没有左子树了(中序里它的左边都处理完了)。

    • 于是不断弹出栈顶,并让 inorderIndex++,直到栈顶节点不等于 inorder[inorderIndex] 或者栈空。

    • 此时最后弹出的那个节点,它的右孩子就是当前前序节点。

    • 于是 node.right = new TreeNode(preorderVal),并压栈。

把前序和中序对照看:

  • 前序:3, 9, 20, 15, 7

  • 中序:9, 3, 15, 20, 7

过程模拟:

步骤

前序值

栈状态(栈顶在右)

inorderIndex

动作

初始

3

[3]

0 (inorder[0]=9)

根入栈

i=1

9

[3,9]

0

3≠9,9 是 3 的左孩子

i=2

20

[3,9]

0

栈顶9inorder[0]=9,弹出9,index=1;栈顶3inorder[1]=3,弹出3,index=2;此时栈顶为空/不匹配,20 是最后弹出节点3的右孩子

i=3

15

[20,15]

2 (inorder[2]=15)

20≠15,15 是 20 的左孩子

i=4

7

[20,15]

2

栈顶15inorder[2]=15,弹出15,index=3;栈顶20inorder[3]=20,弹出20,index=4;7 是最后弹出节点20的右孩子

  1. 若 preorder 为空,返回 null。

  2. 用 preorder[0] 创建根节点 root,压入栈。

  3. inorderIndex = 0。

  4. 从 i = 1 遍历 preorder:

    • 取当前值 preorderVal,查看栈顶 node。

    • 若 node.val != inorder[inorderIndex]:

      • 当前节点是 node 的左孩子,创建并压栈。

    • 否则:

      • 不断弹出栈顶,同时 inorderIndex++,直到栈空或栈顶值不等于 inorder[inorderIndex]。

      • 最后弹出的节点 node 的右孩子就是当前节点,创建并压栈。

  5. 返回 root。

代码:

class Solution {
​
  public TreeNode buildTree(int[] preorder, int[] inorder) {
     if(preorder == null || preorder.length == 0){
       return null;
     }
     TreeNode root = new TreeNode(preorder[0]);
     Deque<TreeNode> stack = new LinkedList<TreeNode>();
     stack.push(root);
     int inorderIndex = 0;
     for(int i = 1;i < preorder.length;i++){
       int preorderVal = preorder[i];
       TreeNode node = stack.peek();
       if(node.val != inorder[inorderIndex]){
         node.left = new TreeNode(preorderVal);
         stack.push(node.left);
       } else{
         while(!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]){
           node = stack.pop();
           inorderIndex++;
         }
         node.right = new TreeNode(preorderVal);
         stack.push(node.right);
       }
     }
     return root;
  }
}

37.路径总和

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

示例 1:

img
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

示例 2:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3

题解:

这题的要求其实很眼熟阿,在一个数据结构找到targetSum,对于这种问题我们可以使用前缀和,写起来简单还快。

class Solution {
​
  public int pathSum(TreeNode root, int targetSum) {
     Map<Long,Integer> prefix = new HashMap<Long,Integer>();
     prefix.put(0L,1);
     return dfs(root,prefix,0,targetSum);
​
  }
  public int dfs(TreeNode root,Map<Long,Integer> prefix,long curr,int targetSum){
     if(root == null){
       return 0;
     }
     int ret = 0;
     curr += root.val;
     ret = prefix.getOrDefault(curr - targetSum,0);
     prefix.put(curr, prefix.getOrDefault(curr, 0) + 1);
     ret += dfs(root.left,prefix,curr,targetSum);   
     ret += dfs(root.right,prefix,curr,targetSum);
     prefix.put(curr,prefix.getOrDefault(curr,0) - 1);
     return ret;
  }
}

38.二叉树的最近公共祖先

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

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

示例 1:

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

示例 2:

img
输入: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

题解:

这题通过遍历二叉树存储父节点,用map存储,用子节点的值为key,父节点为值,这样就能通过子节点拿到父节点。再定义一个记录是否访问过的visited数组来做标记。

class Solution {
​
  Map<Integer, TreeNode> parent = new HashMap<Integer, TreeNode>();
  Set<Integer> visited = new HashSet<Integer>();
​
  public void dfs(TreeNode root){
      if(root.left != null){
        parent.put(root.left.val,root);
        dfs(root.left);
      }
      if(root.right != null){
        parent.put(root.right.val,root);
        dfs(root.right);
      }
  }
  public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
      dfs(root);
      while(p != null){
        visited.add(p.val);
        p = parent.get(p.val);
      }
      while(q != null){
        if(visited.contains(q.val)){
          return q;
        }
        q = parent.get(q.val);
      }
      return null;
  }
}

39二叉树路径和最大值

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例 1:

img
输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

img
输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

题解:

这道题在困难里面属于萝莉,简单通过递归计算每一个子树的路径和,然后通过max找最大就行了。注意树节点的值是可以为负数的,所以maxsum不能初始化为0,否则在max判断一直会是0.

class Solution {
    //初始化为整形最小值防止负值的路径和
  int maxSum = Integer.MIN_VALUE;
​
  public int maxPathSum(TreeNode root) {
     maxGain(root);
     return maxSum;
  }
​
  public int maxGain(TreeNode node){
     if(node == null){
       return 0;
     }
     int leftGain = Math.max(maxGain(node.left),0);
     int rightGain = Math.max(maxGain(node.right),0);
     int priceNewpath = node.val + leftGain + rightGain;
     maxSum = Math.max(maxSum,priceNewpath);
     return node.val + Math.max(leftGain,rightGain);
  }
}


二叉树章节算法思想总结

本章 15 题(第 25 ~ 39 题)可以概括成一句话:二叉树的题,九成是「先选一种遍历顺序,再决定这一步该干什么」。

一、三种基本遍历骨架

1. 递归 DFS(前 / 中 / 后序只差一行的位置)

void traverse(TreeNode root) {
  if (root == null) {
    return;                // 终止条件
  }
  // 1. 前序位置:刚进入节点时执行
  traverse(root.left);
  // 2. 中序位置:左子树处理完之后执行
  traverse(root.right);
  // 3. 后序位置:子树全部处理完之后执行
}

2. 迭代中序(显式栈)

Deque<TreeNode> stack = new ArrayDeque<>();
while (root != null || !stack.isEmpty()) {
  while (root != null) {
    stack.push(root);      // 一路向左压栈
    root = root.left;
  }
  root = stack.pop();      // 弹栈 = 访问当前最小的节点
  root = root.right;       // 转向右子树,重复上述过程
}

3. 层序 BFS(队列 + 分层快照)

Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
  int size = queue.size();   // 关键:先快照本层节点数
  while (size-- > 0) {
    TreeNode cur = queue.poll();
    // 处理 cur
    if (cur.left != null) {
      queue.offer(cur.left);
    }
    if (cur.right != null) {
      queue.offer(cur.right);
    }
  }
}

骨架

适用题型

时间

空间

特点

递归 DFS

绝大多数题

O(n)

O(h)

代码最短,深度大时可能爆栈

迭代中序(栈)

BST 有序性、第 k 小

O(n)

O(h)

可以提前返回,不必一条路走到黑

层序 BFS

按层处理、右视图

O(n)

O(w)

天然分层,宽度大时较费内存

二、递归解题三要素与「前序位置 / 后序位置」

写树递归只问三件事:

  1. 函数语义:这个函数返回什么?(「子树最大深度」/「两棵子树是否互为镜像」/「最大单侧增益」)

  2. 终止条件:什么时候可以直接返回?(通常是 root == null)

  3. 单层逻辑:拿到子问题的结果后,当前节点要做什么?

位置决定思路:

位置

数据流向

典型题目

一句话

前序位置(自顶向下)

把父节点的状态 / 约束传给孩子

32 验证 BST、37 路径总和 III

参数即上下文,必要时回溯撤销

后序位置(自底向上)

把子树的结果汇总给父节点

26 最大深度、29 直径、39 最大路径和

返回值即子问题答案,顺路更新全局答案

口诀:往下带约束用前序,往上要答案用后序。

三、题型分类与套路对照表

分组

题号

题目

核心思想

套路关键词

遍历类

25

二叉树中序遍历

三行顺序决定前 / 中 / 后序

递归 / 显式栈 / Morris

遍历类

30

二叉树层序遍历

队列 + 每层 size 快照

BFS 分层

遍历类

34

二叉树右视图

每层最右节点

BFS 取末位 / DFS 先右后左

深度高度类

26

二叉树的最大深度

max(左, 右) + 1

后序汇总

深度高度类

29

二叉树的直径

左右子树深度之和的最大值

后序 + 全局答案

深度高度类

39

二叉树中的最大路径和

单侧增益 + 拐点结算

后序 + 全局答案 + max(·, 0)

结构变换类

27

翻转二叉树

递归交换左右子树

前序 / 后序皆可,中序不行

结构变换类

31

将有序数组转为 BST

中点作根

二分 + 递归

结构变换类

35

二叉树展开为链表

先序顺序即链表顺序

先收集、再重连

对称比较类

28

对称二叉树

两棵子树互为镜像

交叉比较 p.left ↔ q.right

BST 性质类

32

验证二叉搜索树

全体后代落在 (lower, higher)

前序传上下界 / 中序递增

BST 性质类

33

BST 中第 k 小的元素

中序第 k 个即答案

迭代中序 + 计数提前返回

构造类

36

先序 + 中序构造二叉树

前序定根、中序划区间

递归分治 / 栈 + inorderIndex

路径祖先类

37

路径总和 III

前缀和之差

前缀和 Map + 回溯撤销

路径祖先类

38

二叉树的最近公共祖先

父节点映射 + 祖先标记

哈希表 / 后序递归

四、三个高频通用模板

模板 A:后序汇总 + 全局答案(26 / 29 / 39)

int ans = <合适的初值>;              // 39 题必须是 Integer.MIN_VALUE

int dfs(TreeNode node) {
  if (node == null) {
    return 0;                        // 子问题答案(空节点)
  }
  int left = dfs(node.left);
  int right = dfs(node.right);
  ans = Math.max(ans, <用 left、right 拼出的完整答案>);  // 结算"以当前节点为拐点"
  return <只能选一侧的值>;            // 向上汇报,不能分叉
}

模板 B:自顶向下带状态 + 回溯撤销(32 / 37)

void dfs(TreeNode node, <状态参数>) {
  if (node == null) {
    return;
  }
  <进入节点:更新状态 / 登记前缀和>
  <结算答案>
  dfs(node.left, <新状态>);
  dfs(node.right, <新状态>);
  <离开节点:撤销状态(回溯)>
}

模板 C:中序有序性的三种用法(31 / 33 / 36)

// 升序数组 → 平衡 BST:中点即根
TreeNode build(int[] nums, int l, int r) {
  if (l > r) {
    return null;
  }
  int mid = l + (r - l) / 2;
  TreeNode root = new TreeNode(nums[mid]);
  root.left = build(nums, l, mid - 1);
  root.right = build(nums, mid + 1, r);
  return root;
}

中序是 BST 的「排序视图」:建树用它(31)、找第 k 小用它(33)、还原结构也用它(36)。


评论