Plantre Plantre
首页
  • 算法

    • 查找
    • 排序
  • 力扣

    • 排序
技术
硬件
逆向
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 技术

    • 技术文档
    • GitHub技巧
    • Nodejs
    • 博客搭建
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

plantre

一个后端开发者
首页
  • 算法

    • 查找
    • 排序
  • 力扣

    • 排序
技术
硬件
逆向
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 技术

    • 技术文档
    • GitHub技巧
    • Nodejs
    • 博客搭建
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 计算机组成原理

  • 操作系统

  • 计算机网络

  • 设计模式

  • Java

  • Spring

  • SpringCloud

  • MySQL

  • Redis

  • 分布式

  • Zookeeper

  • Dubbo

  • Kafka

  • 数据结构

  • 算法

  • OJ

    • 自定义
    • 排序
    • 位运算
    • 二分查找
    • 递归
    • 双指针(逆向,快慢)
    • 滑动窗口
    • 辅助栈
    • 贪心
    • 回溯
    • 动态规划
    • 二叉树
      • DFS
      • 拼接&拆分
      • 模拟
      • 工业实现原理
      • 数学
      • 字符串
    • 从道家哲学看计算机?
    • 后端
    • OJ
    plantre
    2025-06-12
    目录

    二叉树

    # 144. 二叉树的前序遍历 - 力扣(LeetCode) (opens new window)

    # 递归
    class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
            preOrder(root, res);
            return res;
        }
    
        public void preOrder(TreeNode root,List<Integer> res){
            if (root == null) {
                return;
            }
            res.add(root.val);
            preOrder(root.left,res);
            preOrder(root.right,res);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 非递归
    class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
            if (root == null) {
                return res;
            }
            Deque<TreeNode> stack = new LinkedList<TreeNode>();
            TreeNode node = root;
            while (!stack.isEmpty() || node != null) {
                while (node != null) {
                    res.add(node.val);
                    stack.push(node);
                    node = node.left;
                }
                node = stack.pop();
                node = node.right;
            }
            return res;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

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

    # 递归
    class Solution {
        public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
            inOrder(root,res);
            return res;
        }
    
        public void inOrder(TreeNode root,List<Integer> res) {
            if (root == null) {
                return;
            }
            inOrder(root.left,res);
            res.add(root.val);
            inOrder(root.right,res);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 非递归
    class Solution {
        public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
            Deque<TreeNode> stack = new LinkedList<TreeNode>();
            while (!stack.isEmpty() || root != null) {
                while (root != null) {
                    stack.push(root);
                    root = root.left;
                }
                root = stack.pop();
                res.add(root.val);
                root = root.right;
            }
            return res;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    # 145. 二叉树的后序遍历 - 力扣(LeetCode) (opens new window)

    # 递归
    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
            postOrder(root, res);
            return res;
        }
    
        public void postOrder(TreeNode root,List<Integer> res) {
            if (root == null) {
                return;
            }
            postOrder(root.left,res);
            postOrder(root.right,res);
            res.add(root.val);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 非递归
    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<Integer>();
             if (root == null) {
                return res;
            }
            Deque<TreeNode> stack = new LinkedList<TreeNode>();
            TreeNode prev = null;
            while (root!=null || !stack.isEmpty()) {
                while (root != null) {
                    stack.push(root);
                    root = root.left;
                }
                root = stack.pop();
                if (root.right == null || root.right == prev) {
                    res.add(root.val);
                    prev = root;
                    root = null;
                } else {
                    stack.push(root);
                    root = root.right;
                }
            }
            return res;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

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

    class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            List<List<Integer>> ans = new ArrayList<List<Integer>>();
            if (root == null) {
                return ans;
            }
            Queue<TreeNode> queue = new LinkedList<TreeNode>();
            queue.offer(root);
            while (!queue.isEmpty()) {
                List<Integer> level = new ArrayList<Integer>();
                int currentLevelSize = queue.size();
                for (int i = 1;i <= currentLevelSize; ++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;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    # 103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode) (opens new window)

    class Solution {
        public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
            List<List<Integer>> ans = new ArrayList<List<Integer>>();
            if (root == null) {
                return ans;
            }
            Queue<TreeNode> queue = new LinkedList<TreeNode>();
            queue.offer(root);
            boolean orderLeft = true;
            while (!queue.isEmpty()) {
                Deque<Integer> level = new LinkedList<Integer>();
                int currentLevelSize = queue.size();
                for (int i = 1;i <= currentLevelSize; ++i) {
                    TreeNode node = queue.poll();
                    if (orderLeft) {
                        level.offerLast(node.val);
                    }else{
                        level.offerFirst(node.val);
                    }
                    if (node.left != null) {
                        queue.offer(node.left);
                    }
                    if (node.right != null) {
                        queue.offer(node.right);
                    }
                }
                ans.add(new LinkedList<Integer>(level));
                orderLeft =! orderLeft;
            }
            return ans;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    # 105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode) (opens new window)

    class Solution {
        HashMap<Integer, Integer> valToIndex = new HashMap<>();
    
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            for (int i = 0;i < inorder.length; i++) {
                valToIndex.put(inorder[i],i);
            }
            return build(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
        }
    
        TreeNode build(int[] preorder,int preStart,int preEnd,int[] inorder,int intStart,int inEnd) {
            if (preStart > preEnd) {
                return null;
            }
            int rootVal = preorder[preStart];
            int index = valToIndex.get(rootVal);
            // int index = 0;
            // for (int i = intStart;i <= inEnd; i++) {
            //     if (inorder[i] == rootVal) {
            //         index = i;
            //         break;
            //     }
            // }
            TreeNode root = new TreeNode(rootVal);
            int leftSize = index - intStart;
            root.left = build(preorder, preStart + 1, preStart + leftSize, inorder, intStart, index - 1);
            root.right = build(preorder, preStart + leftSize + 1, preEnd, inorder, index + 1, inEnd);
            return root;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

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

    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            //base
            if (root == null) return null;
            if (root == p || root == q) return root;
            
            TreeNode left = lowestCommonAncestor(root.left,p,q);
            TreeNode right = lowestCommonAncestor(root.right,p,q);
            //当 left 和 right 同时为空 :说明 root 的左 / 右子树中都不包含 p,q ,返回 null ;
            if (left == null && right == null) {
                return null;
            }
            //p,q 都不在 root 的左子树中,直接返回 right 
            //1)p,q 其中一个在 root 的 右子树 中,此时 right 指向 p(假设为 p );
            //2)p,q 两节点都在 root 的 右子树 中,此时的 right 指向 最近公共祖先节点 ;
            if (left == null) return right;
            if (right == null) return left;
            //当 left 和 right 同时不为空 :说明 p,q 分列在 root 的 异侧 (分别在 左 / 右子树),因此 root 为最近公共祖先,返回 root ;
            return root;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    # 226. 翻转二叉树 - 力扣(LeetCode) (opens new window)

    class Solution {
        public TreeNode invertTree(TreeNode root) {
            if (root == null) return null;
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            invertTree(root.left);
            invertTree(root.right);
            return root;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Solution {
        public TreeNode invertTree(TreeNode root) {
            if (root == null) return null;
            invertTree(root.left);
            invertTree(root.right);
            // 交换在递归之后
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            return root;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    BFS层序遍历

    class Solution {
        public TreeNode invertTree(TreeNode root) {
            if (root == null) return null;
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(root);
            while(!queue.isEmpty()) {
                TreeNode node = queue.poll();
                TreeNode temp = node.left;
                node.left = node.right;
                node.right = temp;
                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            return root;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    DFS栈模拟

    class Solution {
        public TreeNode invertTree(TreeNode root) {
            if (root == null) return null;
            Deque<TreeNode> stack = new LinkedList<>();
            stack.push(root);
            while (!stack.isEmpty()) {
                TreeNode node = stack.pop();
                // 交换左右子树
                TreeNode temp = node.left;
                node.left = node.right;
                node.right = temp;
                // 右、左子节点入栈
                if (node.right != null) stack.push(node.right);
                if (node.left != null) stack.push(node.left);
            }
            return root;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    # 求和等

    # 124. 二叉树中的最大路径和 - 力扣(LeetCode) (opens new window)

    class Solution {
        private int res = Integer.MIN_VALUE;
    
        public int maxPathSum(TreeNode root) {
            maxGain(root);
            return res;
        }
    
        private int maxGain(TreeNode node) {
            if (node == null) return 0;
            int left = Math.max(maxGain(node.left), 0); // 左贡献
            int right = Math.max(maxGain(node.right), 0); // 右贡献
            res = Math.max(res, node.val + left + right); // 更新全局
            return node.val + Math.max(left, right); // 返回单侧贡献
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    # BFS&DFS

    # 199. 二叉树的右视图 - 力扣(LeetCode) (opens new window)

    广度优先搜索(BFS):层序遍历,取每层最后一个节点

    class Solution {
        public List<Integer> rightSideView(TreeNode root) {
            List<Integer> res = new ArrayList<>();
            if (root == null) return res;
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(root);
            while (!queue.isEmpty()) {
                int size = queue.size();
                for (int i = 0; i < size; i++) {
                    TreeNode node = queue.poll();
                    // 记录当前层最后一个节点
                    if (i == size - 1) res.add(node.val);
                    if (node.left != null) queue.offer(node.left);
                    if (node.right != null) queue.offer(node.right);
                }
            }
            return res;
        } 
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    深度优先搜索(DFS):优先遍历右子树,记录每层首次访问的节点(即最右侧节点)

    class Solution {
    
        private List<Integer> res = new ArrayList<>();
    
        public List<Integer> rightSideView(TreeNode root) {
            dfs(root, 0);
            return res;
        } 
    
        private void dfs(TreeNode node, int depth) {
            if (node == null) return;
            // *******当前层首次访问的节点******
            if (depth == res.size()) res.add(node.val);
            // 需求右视图,先递归右子树
            dfs(node.right, depth + 1);
            dfs(node.left, depth + 1);
        }
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    # 129. 求根节点到叶节点数字之和 - 力扣(LeetCode) (opens new window)

    dfs

    class Solution {
        
        public int sumNumbers(TreeNode root) {
            return dfs(root, 0);
        }
    
        private int dfs(TreeNode node, int currentSum) {
            if (node == null) return 0; 
            currentSum = currentSum * 10 + node.val;
            if (node.left == null && node.right == null) { // 叶子节点
                return currentSum;
            }
            return dfs(node.left, currentSum) + dfs(node.right, currentSum);
        }
        
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    bfs

    class Solution {
    
        public int sumNumbers(TreeNode root) {
            if (root == null) return 0;
            Queue<TreeNode> nodeQueue = new LinkedList<>();
            Queue<Integer> sumQueue = new LinkedList<>();
            nodeQueue.offer(root);
            sumQueue.offer(0);
            int totalSum = 0;
            while (!nodeQueue.isEmpty()) {
                TreeNode node = nodeQueue.poll();
                int currentSum = sumQueue.poll() * 10 +  node.val;
                if (node.left == null && node.right == null) {
                    totalSum += currentSum;
                }
                if (node.left != null) {
                    nodeQueue.offer(node.left);
                    sumQueue.offer(currentSum);
                }
                if (node.right != null) {
                    nodeQueue.offer(node.right);
                    sumQueue.offer(currentSum);
                }
            }
            return totalSum;
        }
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

    # 101. 对称二叉树 - 力扣(LeetCode) (opens new window)

    迭代

    class Solution {
        public boolean isSymmetric(TreeNode root) {
            if (root == null) {
                return true;
            }
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(root.left);
            queue.offer(root.right);
            while (!queue.isEmpty()) {
                TreeNode leftNode = queue.poll();
                TreeNode rightNode = queue.poll();
                // 均空则继续
                if (leftNode == null && rightNode == null) continue;
                 // 一空一非空或值不等
                if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) {
                    return false;
                }
                // 注意入队的顺序,对称性
                queue.offer(leftNode.left);
                queue.offer(rightNode.right);
                queue.offer(leftNode.right);
                queue.offer(rightNode.left);
            }
            return true;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    递归

    class Solution {
        public boolean isSymmetric(TreeNode root) {
            if (root == null) {
                return true;
            }
            return check(root.left, root.right);
        }
        private boolean check(TreeNode p, TreeNode q) {
            if (p == null && q == null) return true; 
            if (p == null || q == null) return false;
            if (p.val != q.val) return false;
            return check(p.left, q.right) && check(p.right, q.left);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

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

    递归

    class Solution {
        public int maxDepth(TreeNode root) {
            if (root == null) return 0;
            int leftDepth = maxDepth(root.left);
            int rightDepth = maxDepth(root.right);
            return Math.max(leftDepth, rightDepth) + 1;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    bfs

    class Solution {
        public int maxDepth(TreeNode root) {
            if (root == null) return 0;
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(root);
            int depth = 0;
            while (!queue.isEmpty()) {
                int levelSize = queue.size();
                for (int i = 0; i < levelSize; i++) {
                    TreeNode node = queue.poll();
                    if (node.left != null) queue.offer(node.left);
                    if (node.right != null) queue.offer(node.right);
                }
                depth++;
            }
            return depth;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    # 662. 二叉树最大宽度 - 力扣(LeetCode) (opens new window)

    BFS层序遍历(推荐)

    class Solution {
        public int widthOfBinaryTree(TreeNode root) {
            if (root == null) return 0;
            Queue<Pair<TreeNode, Integer>> queue = new LinkedList<>();
            queue.offer(new Pair<>(root, 1));
            int maxWidth = 0;
            while (!queue.isEmpty()) {
                int size = queue.size();
                // 当前层首节点编号
                int firstIndex = queue.peek().getValue();
                int lastIndex = firstIndex;
                for (int i = 0; i < size; i++) {
                    Pair<TreeNode, Integer> pair = queue.poll();
                    TreeNode node = pair.getKey();
                    // 更新尾节点编号
                    lastIndex = pair.getValue();
                    if (node.left != null) {
                        queue.offer(new Pair<>(node.left, 2 * lastIndex));
                    }
                    if (node.right != null) {
                        queue.offer(new Pair<>(node.right, 2 * lastIndex + 1));
                    }
                }
                // 每层的宽度即为该层​​最大编号 - 最小编号 + 1​​。此方法避免显式存储空节点,仅通过非空节点的编号计算宽度
                maxWidth = Math.max(maxWidth, lastIndex - firstIndex + 1);
            }
            return maxWidth;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    dfs

    class Solution {
    
        private int maxWidth = 0;
        // 存储每层最左节点编号
        private List<Integer> leftMost = new ArrayList<>(); // 存储每层最左节点编号
    
        public int widthOfBinaryTree(TreeNode root) {
            dfs(root, 1, 0);
            return maxWidth;
        }
    
        private void dfs(TreeNode node, int index, int depth) {
            if (node == null) return;
             // 首次到达新层级,记录最左节点编号
            if (depth == leftMost.size()) {
                leftMost.add(index);       
            }
            maxWidth = Math.max(maxWidth, index - leftMost.get(depth) + 1);
            dfs(node.left, 2 * index, depth + 1);
            dfs(node.right, 2 * index + 1, depth + 1);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    # 110. 平衡二叉树 - 力扣(LeetCode) (opens new window)

    方法 方向 遍历顺序 时间复杂度 优势/劣势
    自顶向下 根节点→叶节点 前序遍历 O(n²) 直观,但重复计算子树高度,效率低
    自底向上 叶节点→根节点 后序遍历 O(n) 无重复计算,提前终止不平衡子树

    推荐方法:自底向上(后序遍历),避免重复计算,效率更优。

    class Solution {
        // 高度(Height):从​​当前节点到最远叶子​​的路径节点数(本题使用)
        // 深度(Depth):从​​根节点到当前节点​​的路径节点数
        public boolean isBalanced(TreeNode root) {
            return dfs(root) != -1;
        }
    
        private int dfs(TreeNode root) {
            if (root == null) return 0;
            int leftHeight = dfs(root.left);
            if (leftHeight == -1) return -1;
            int rightHeight = dfs(root.right);
            if (rightHeight == -1) return -1;
            // 比较左右子树高度差,若>1则返回-1;否则返回当前树高度max(left, right) + 1
            if (Math.abs(leftHeight - rightHeight) > 1) return -1;
            // 当前节点高度 = 最深子树的高度 + 自身​
            return Math.max(leftHeight, rightHeight) + 1;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    # 543. 二叉树的直径 - 力扣(LeetCode) (opens new window)

    class Solution {
        // 记录最大路径节点数(直径+1)
        private int maxDiameter = 0;
    
        public int diameterOfBinaryTree(TreeNode root) {
            maxDepth(root);
            // 路径长度 = 节点数 - 1
            return maxDiameter - 1;
        }
    
        private int maxDepth(TreeNode node) {
            if (node == null) return 0;
            // 左子树深度
            int leftDepth = maxDepth(node.left);
            int rightDepth = maxDepth(node.right);
            // 更新全局最大值:当前节点为转折点的路径节点数
            maxDiameter = Math.max(maxDiameter, leftDepth + rightDepth + 1);
            // 返回当前子树的深度
            return Math.max(leftDepth, rightDepth) + 1;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    # 98. 验证二叉搜索树 - 力扣(LeetCode) (opens new window)

    class Solution {
        public boolean isValidBST(TreeNode root) {
            // 调用递归方法,初始范围是 (-infinity, infinity)
            /**
            如果我们使用一个固定的值(例如 Integer.MIN_VALUE 或 Integer.MAX_VALUE),
            可能会限制树的值的范围,导致错误判断。
            因此,使用 Long 类型的最小值和最大值可以处理所有可能的节点值,避免溢出和边界问题
             */
            return validate(root, Long.MIN_VALUE, Long.MAX_VALUE);
        }
    
        private boolean validate(TreeNode node, long minVal, long maxVal) {
            if (node == null) return true;
            // 当前节点值必须在 (low, high) 范围内
            if (node.val <= minVal || node.val >= maxVal) return false;
            // 递归检查左右子树
            // 对于左子树,右边界是当前节点的值
            // 对于右子树,左边界是当前节点的值
            return validate(node.left, minVal, node.val) && validate(node.right, node.val, maxVal);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    中序遍历递归法

    class Solution {
        private TreeNode prev = null; // 保存前驱节点
    
        public boolean isValidBST(TreeNode root) {
            if (root == null) return true;
            if (!isValidBST(root.left)) return false;
            // 检查当前节点是否 > 前驱节点
            if (prev != null && root.val <= prev.val) return false;
            prev = root;
            return isValidBST(root.right);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    中序遍历迭代栈法

    class Solution {
        private TreeNode prev = null; // 保存前驱节点
    
        public boolean isValidBST(TreeNode root) {
            Deque<TreeNode> stack = new LinkedList<>();
            TreeNode prev = null; // 前驱节点指针
            TreeNode cur = root;
            while (cur != null || !stack.isEmpty()) {
                 while (cur != null) { 
                    stack.push(cur);
                    cur = cur.left;
                 }
                 cur = stack.pop();
                  // 检查是否严格递增
                 if (prev != null && cur.val <= prev.val) {
                    return false;
                }
                // 更新前驱节点
                prev = cur;
                // 转向右子树
                cur = cur.right;
            }
            return true;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    # 112. 路径总和 - 力扣(LeetCode) (opens new window)

    bfs

    class Solution {
        public boolean hasPathSum(TreeNode root, int targetSum) {
            if (root == null) return false;
            Queue<Pair<TreeNode, Integer>> queue = new LinkedList<>();
            queue.offer(new Pair<>(root, root.val));
            while (!queue.isEmpty()) {
                Pair<TreeNode, Integer> pair = queue.poll();
                TreeNode node = pair.getKey();
                int currSum = pair.getValue();
                if (node.left == null && node.right == null && currSum == targetSum) {
                    return true;
                }
                if (node.left != null) {
                    queue.offer(new Pair<>(node.left, currSum + node.left.val));
                }
                if (node.right != null) {
                    queue.offer(new Pair<>(node.right, currSum + node.right.val));
                }
            }
            return false;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    递归

    class Solution {
        public boolean hasPathSum(TreeNode root, int targetSum) {
            if (root == null) return false;
            if (root.left == null && root.right == null) {
                return targetSum == root.val;
            }
            return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    # 113. 路径总和 II - 力扣(LeetCode) (opens new window)

    dfs+回溯

    class Solution {
    
        private List<List<Integer>> result = new ArrayList<>();
        private List<Integer> path = new ArrayList<>();
    
        public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
            dfs(root, targetSum);
            return result;
        }
    
        private void dfs(TreeNode node, int remain) {
            if (node == null) return;
            // 1. 添加当前节点值,更新剩余目标
            path.add(node.val);
            remain -= node.val;
            // 2. 到达叶子节点且目标和为0
            if (node.left == null && node.right == null && remain == 0) {
                // 深拷贝当前路径
                result.add(new ArrayList<>(path));
            }
            // 3. 递归遍历左右子树
            dfs(node.left, remain);
            dfs(node.right, remain);
            // 4. 回溯:移除当前节点
            path.remove(path.size() - 1);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    编辑 (opens new window)
    上次更新: 2025/07/25, 12:08:10
    动态规划
    DFS

    ← 动态规划 DFS→

    最近更新
    01
    加油鸭
    07-30
    02
    要点总结
    07-28
    03
    字符串
    07-15
    更多文章>
    Theme by Vdoing | Copyright © 2025-2025 plantre | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式