LeetCode 热题 100 之 543. 二叉树的直径 102. 二叉树的层序遍历 108. 将有序数组转换为二叉搜索树 98. 验证二叉搜索树

  1. 二叉树的直径

  2. 二叉树的层序遍历

  3. 将有序数组转换为二叉搜索树

  4. 验证二叉搜索树

543. 二叉树的直径

复制代码
/**
 * 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 {
    private int maxDiameter = 0;

    public int diameterOfBinaryTree(TreeNode root) {
        maxDiameter = 0;
        depth(root);
        return maxDiameter;
    }

    // 计算以 node 为根的子树深度,同时更新 maxDiameter
    private int depth(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int leftDepth = depth(node.left);  // 左子树深度
        int rightDepth = depth(node.right); // 右子树深度
        // 更新最大直径:当前节点的直径 = leftDepth + rightDepth
        maxDiameter = Math.max(maxDiameter, leftDepth + rightDepth);
        // 返回当前节点的子树深度(取左右子树最大深度 +1)
        return Math.max(leftDepth, rightDepth) + 1;
    }
}

class Solution {
    private int ans;

    public int diameterOfBinaryTree(TreeNode root) {
        dfs(root);
        return ans;
    }

    private int dfs(TreeNode node) {
        if (node == null) {
            return -1; // 对于叶子来说,链长就是 -1+1=0
        }
        int lLen = dfs(node.left) + 1; // 左子树最大链长+1
        int rLen = dfs(node.right) + 1; // 右子树最大链长+1
        ans = Math.max(ans, lLen + rLen); // 两条链拼成路径
        return Math.max(lLen, rLen); // 当前子树最大链长
    }
}

作者:灵茶山艾府
链接:https://leetcode.cn/problems/diameter-of-binary-tree/solutions/2227017/shi-pin-che-di-zhang-wo-zhi-jing-dpcong-taqma/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解题思路:后序遍历(DFS)

直径 = 树中任意两节点之间最长路径的边数

路径可能经过根节点,也可能不经过

核心公式:对任意节点,以它为 "拐点" 的直径 = 左子树深度 + 右子树深度

102. 二叉树的层序遍历

复制代码
/**
 * 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; // 空树直接返回空列表
        }
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root); // 根节点入队
        
        while (!queue.isEmpty()) {
            int levelSize = queue.size(); // 当前层的节点数
            List<Integer> currentLevel = new ArrayList<>();
            
            // 遍历当前层所有节点
            for (int i = 0; i < levelSize; i++) {
                TreeNode node = queue.poll();
                currentLevel.add(node.val); // 记录当前节点值
                
                // 左子节点非空则入队
                if (node.left != null) {
                    queue.offer(node.left);
                }
                // 右子节点非空则入队
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            res.add(currentLevel); // 将当前层结果加入总列表
        }
        return res;
    }
}

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        if (root == null) {
            return List.of();
        }
        List<List<Integer>> ans = new ArrayList<>();
        Queue<TreeNode> q = new ArrayDeque<>();
        q.add(root);
        while (!q.isEmpty()) {
            int n = q.size();
            List<Integer> vals = new ArrayList<>(n); // 预分配空间
            while (n-- > 0) {
                TreeNode node = q.poll();
                vals.add(node.val);
                if (node.left != null)  q.add(node.left);
                if (node.right != null) q.add(node.right);
            }
            ans.add(vals);
        }
        return ans;
    }
}

作者:灵茶山艾府
链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/solutions/2049807/bfs-wei-shi-yao-yao-yong-dui-lie-yi-ge-s-xlpz/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解题思路1:一个队列
  1. 队列初始化:将根节点入队,作为遍历起点。

  2. 层遍历循环

  • 每次循环开始时,队列中存放的是当前层的所有节点 ,用 levelSize 记录该层节点数。

  • 遍历当前层所有节点:

    • 取出节点并将其值加入当前层列表。

    • 将非空的左右子节点入队,作为下一层的待处理节点。

  • 将当前层列表加入结果集,完成一层的处理。

  1. 边界处理 :空树直接返回空列表,单节点树返回 [[root.val]],符合题目要求。

    class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
    if (root == null) {
    return List.of();
    }
    List<List<Integer>> ans = new ArrayList<>();
    List<TreeNode> cur = List.of(root);
    while (!cur.isEmpty()) {
    List<TreeNode> nxt = new ArrayList<>();
    List<Integer> vals = new ArrayList<>(cur.size()); // 预分配空间
    for (TreeNode node : cur) {
    vals.add(node.val);
    if (node.left != null) nxt.add(node.left);
    if (node.right != null) nxt.add(node.right);
    }
    cur = nxt;
    ans.add(vals);
    }
    return ans;
    }
    }

    作者:灵茶山艾府
    链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/solutions/2049807/bfs-wei-shi-yao-yao-yong-dui-lie-yi-ge-s-xlpz/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解题思路2:两个数组

108. 将有序数组转换为二叉搜索树

复制代码
/**
 * 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 sortedArrayToBST(int[] nums) {
        return build(nums, 0, nums.length - 1);
    }

    // 递归构建:在 [left, right] 区间内生成平衡 BST
    private TreeNode build(int[] nums, int left, int right) {
        // 终止条件:区间为空,返回 null
        if (left > right) {
            return null;
        }
        // 选择中间位置作为根节点(保证平衡)
        int mid = left + (right - left) / 2; // 避免溢出
        TreeNode node = new TreeNode(nums[mid]);
        // 递归构建左子树(左半区间)
        node.left = build(nums, left, mid - 1);
        // 递归构建右子树(右半区间)
        node.right = build(nums, mid + 1, right);
        return node;
    }
}

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return dfs(nums, 0, nums.length);
    }

    // 定义:把 nums[left ... right-1] 转成平衡二叉搜索树
    private TreeNode dfs(int[] nums, int left, int right) {
        // 区间为空,返回 null
        if (left == right) {
            return null;
        }
        // 无符号右移,等价于 (left+right)/2,但是不会溢出
        int m = (left + right) >>> 1;
        
        // 构造节点:
        // 左孩子 = 左半区间 [left, m)
        // 右孩子 = 右半区间 [m+1, right)
        return new TreeNode(
            nums[m],
            dfs(nums, left, m),
            dfs(nums, m + 1, right)
        );
    }
}
解题思路:递归分治法

区间划分

  • leftright 定义当前处理的数组区间。

  • left > right 时,区间为空,返回 null

根节点选择

  • 取区间中点 mid 作为根节点,使左右子树节点数尽可能相等,保证树的平衡。

  • left + (right - left) / 2 替代 (left + right) / 2,避免整数溢出。

递归 构建

  • 左子树:[left, mid-1]

  • 右子树:[mid+1, right]

  • 最终得到的树天然满足 BST 性质(左 < 根 < 右)且高度平衡。

98. 验证二叉搜索树

复制代码
/**
 * 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 isValidBST(TreeNode root) {
        // 用 Long 避免边界值溢出(如 node.val = Integer.MIN_VALUE)
        return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    private boolean isValidBST(TreeNode node, long low, long high) {
        // 空节点天然合法
        if (node == null) return true;
        // 节点值不在区间内 → 不合法
        if (node.val <= low || node.val >= high) return false;
        // 递归校验左右子树
        return isValidBST(node.left, low, node.val) 
            && isValidBST(node.right, node.val, high);
    }
}
解法思路1:递归法(约束范围)

思路:给每个节点规定一个取值区间 (low, high),节点值必须在这个区间内才合法。

  • 根节点:(-∞, +∞)

  • 左孩子:继承父节点的 low,上限为父节点值

  • 右孩子:继承父节点的 high,下限为父节点值

解法 1: 前序遍历 ・区间约束法

每个节点必须在 (left, right) 区间内

  • 左子树:上限 = 当前节点值

  • 右子树:下限 = 当前节点值

    class Solution {
    public boolean isValidBST(TreeNode root) {
    return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    复制代码
      private boolean isValidBST(TreeNode node, long left, long right) {
          if (node == null) {
              return true;
          }
          long x = node.val;
          return left < x && x < right &&
                 isValidBST(node.left, left, x) &&
                 isValidBST(node.right, x, right);
      }

    }

解法 2: 中序遍历 ・升序判断法

BST 中序遍历 一定是严格递增的

只要出现 当前值 ≤ 上一个值 就不是 BST

复制代码
class Solution {
    private long pre = Long.MIN_VALUE;

    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        if (!isValidBST(root.left)) { // 左
            return false;
        }
        if (root.val <= pre) { // 中
            return false;
        }
        pre = root.val;
        return isValidBST(root.right); // 右
    }
}

解法 3: 后序遍历 ・子树最值法

返回每棵子树的 [最小值,最大值]

  • 当前节点 > 左子树最大值

  • 当前节点 < 右子树最小值满足才是 BST

    class Solution {
    public boolean isValidBST(TreeNode root) {
    return dfs(root)[1] != Long.MAX_VALUE;
    }

    复制代码
      private long[] dfs(TreeNode node) {
          if (node == null) {
              return new long[]{Long.MAX_VALUE, Long.MIN_VALUE};
          }
          long[] left = dfs(node.left);
          long[] right = dfs(node.right);
          long x = node.val;
          // 也可以在递归完左子树之后立刻判断,如果发现不是二叉搜索树,就不用递归右子树了
          if (x <= left[1] || x >= right[0]) {
              return new long[]{Long.MIN_VALUE, Long.MAX_VALUE};
          }
          return new long[]{Math.min(left[0], x), Math.max(right[1], x)};
      }

    }

解法思路2:前中后序遍历

总结

本文整理了四道二叉树高频经典题:二叉树直径通过后序 DFS 计算左右子树深度之和求得最长路径;层序遍历采用 BFS 队列或双列表实现按层遍历;有序数组转平衡 BST 使用递归分治,取中间节点为根保证平衡;验证二叉搜索树则可通过前序区间约束、中序递增判断、后序子树最值三种方法,利用 BST 严格有序特性完成校验。整体覆盖 DFS、BFS、递归分治与二叉搜索树核心性质,是二叉树基础题型的通用解题模板。

相关推荐
计算机安禾2 小时前
【数据结构与算法】第19篇:树与二叉树的基础概念
c语言·开发语言·数据结构·c++·算法·visual studio code·visual studio
副露のmagic2 小时前
哈希章节 leetcode 思路&实现
算法·leetcode·哈希算法
副露のmagic2 小时前
字符串章节 leetcode 思路&实现
windows·python·leetcode
csuzhucong2 小时前
puzzle(1037)黑白、黑白棋局
算法
XiYang-DING2 小时前
【LeetCode】链表 + 快慢指针找中间 | 2095. 删除链表的中间节点
算法·leetcode·链表
Zarek枫煜2 小时前
[特殊字符] C3语言:传承C之高效,突破C之局限
c语言·开发语言·c++·单片机·嵌入式硬件·物联网·算法
寻寻觅觅☆3 小时前
东华OJ-基础题-30-求最晚和最早日期(C++)
数据结构·c++·算法
羊小蜜.3 小时前
Mysql 03: 连接查询全解——内连接、外连接与复合条件查询
数据库·mysql·算法·连接查询
vivo互联网技术3 小时前
CVPR 2026 | C²FG:用分数差异分析提高条件生成中CFG的引导
人工智能·算法·aigc