当前位置: 首页 > news >正文

力扣top100(day02-04)--二叉树 01

94. 二叉树的中序遍历

/*** 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<Integer> inorderTraversal(TreeNode root) {// 创建结果列表,用于存储遍历结果List<Integer> res = new ArrayList<Integer>();// 调用递归辅助方法进行中序遍历inorder(root, res);// 返回遍历结果return res;}/*** 递归实现的中序遍历辅助方法* 中序遍历顺序:左子树 -> 根节点 -> 右子树* @param root 当前遍历的树节点* @param res 存储遍历结果的列表*/public void inorder(TreeNode root, List<Integer> res) {// 递归终止条件:当前节点为空if (root == null) {return;}// 1. 递归遍历左子树inorder(root.left, res);// 2. 访问当前根节点(将节点值加入结果列表)res.add(root.val);// 3. 递归遍历右子树inorder(root.right, res);}
}

关键点说明

  1. 中序遍历顺序

    • 左子树 → 根节点 → 右子树

    • 对于二叉搜索树(BST),中序遍历会产生一个升序序列

  2. 递归实现特点

    • 递归终止条件:当前节点为null时返回

    • 递归过程:严格按照左-根-右的顺序进行递归调用

  3. 时间复杂度分析

    • O(n):需要访问树中的每个节点一次

    • n为二叉树中的节点总数

  4. 空间复杂度分析

    • 最坏情况O(n):当树退化为链表时,递归栈的深度等于节点数

    • 平均情况O(log n):平衡二叉树情况下递归栈深度

示例执行流程

对于如下二叉树:

text

   1\2/3

遍历过程:

  1. 访问节点1,先递归左子树(null,直接返回)

  2. 将1加入结果列表

  3. 访问节点1的右子树(节点2)

    • 访问节点2的左子树(节点3)

      • 访问节点3的左子树(null)

      • 将3加入结果列表

      • 访问节点3的右子树(null)

    • 将2加入结果列表

    • 访问节点2的右子树(null)

  4. 最终结果:[1, 3, 2]

104. 二叉树的最大深度

/*** 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;} else {int leftHeight = maxDepth(root.left);int rightHeight = maxDepth(root.right);return Math.max(leftHeight, rightHeight) + 1;}}
}

关键点说明

  1. 递归思想

    • 一棵树的最大深度 = 左子树和右子树中较大的深度 + 1(当前节点)

    • 这种"自顶向下"分解问题,"自底向上"计算结果的思路是典型的递归解法

  2. 递归终止条件

    • 当节点为null时,深度为0(这是递归的基本情况)

  3. 时间复杂度

    • O(n):需要访问树中的每个节点一次

    • n为二叉树中的节点总数

  4. 空间复杂度

    • 最坏情况O(n):当树退化为链表时,递归栈的深度等于节点数

    • 平均情况O(log n):平衡二叉树情况下递归栈深度

226. 翻转二叉树

/*** 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;}TreeNode left = invertTree(root.left);TreeNode right = invertTree(root.right);root.left = right;root.right = left;return root;}
}

101. 对称二叉树

/*** 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) {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);}
}

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 {int ans;public int diameterOfBinaryTree(TreeNode root) {ans = 1;depth(root);return ans - 1;}public int depth(TreeNode node) {if (node == null) {return 0; // 访问到空节点了,返回0}int L = depth(node.left); // 左儿子为根的子树的深度int R = depth(node.right); // 右儿子为根的子树的深度ans = Math.max(ans, L+R+1); // 计算d_node即L+R+1 并更新ansreturn Math.max(L, R) + 1; // 返回该节点为根的子树的深度}
}

关键点说明

  1. 直径定义

    • 二叉树的直径是任意两个节点间最长路径的长度(边数)

    • 这个路径不一定经过根节点

  2. 算法思路

    • 对于每个节点,计算通过它的最长路径(左子树深度+右子树深度)

    • 在计算深度过程中,不断更新全局最大直径

    • 最终直径为最大节点数-1

  3. 递归过程

    • depth()函数计算子树深度

    • 在计算深度时,同时计算通过当前节点的路径长度(L+R+1)

    • 使用成员变量ans记录全局最大值

  4. 时间复杂度

    • O(n):每个节点只访问一次

    • n为二叉树中的节点总数

  5. 空间复杂度

    • 最坏情况O(n):树退化为链表时递归栈深度

    • 平均情况O(log n):平衡二叉树情况下递归栈深度

示例执行流程

对于如下二叉树:

text

      1/ \2   3/ \     4   5    

计算过程:

  1. 访问节点4:L=0, R=0 → ans=max(1,1)=1 → 返回1

  2. 访问节点5:L=0, R=0 → ans=max(1,1)=1 → 返回1

  3. 访问节点2:L=1(4), R=1(5) → ans=max(1,3)=3 → 返回2

  4. 访问节点3:L=0, R=0 → ans=max(3,1)=3 → 返回1

  5. 访问节点1:L=2(2), R=1(3) → ans=max(3,4)=4 → 返回3

  6. 最终直径:ans-1=3(路径[4,2,1,3]或[5,2,1,3])

为什么这种方法有效?

  1. 最长路径必然经过某个子树的根节点

  2. 通过计算每个节点左右子树深度之和,可以找到所有可能的路径长度

  3. 在计算深度的过程中,我们实际上检查了所有可能的路径

这种递归解法巧妙地将深度计算和直径查找结合在一起,通过一次遍历即可解决问题,效率很高。

递归思想详解

递归是编程中一种非常重要的思想,它通过将大问题分解为相似的小问题来解决问题。让我们深入理解递归的核心概念和应用。

递归的基本原理

递归包含两个关键部分:

  1. 基准条件(Base Case):最简单的情况,可以直接得出答案

  2. 递归条件(Recursive Case):将问题分解为更小的同类问题

递归三要素

  1. 明确函数的功能:清楚知道这个函数要解决什么问题

  2. 寻找递归结束条件:防止无限递归

  3. 找出函数的等价关系式:如何通过更小的问题解决当前问题

递归在二叉树问题中的应用

以计算二叉树最大深度为例:

public int maxDepth(TreeNode root) {// 基准条件:空树的深度为0if (root == null) {return 0;}// 递归条件:当前树深度 = 左右子树中较大的深度 + 1return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}

执行过程分析:

  1. 从根节点开始,先计算左子树深度

  2. 再计算右子树深度

  3. 取两者较大值加1得到当前树的深度

递归的优缺点

优点:

  • 代码简洁清晰

  • 适合处理树形结构、分治问题等

  • 数学表达自然(如斐波那契数列、阶乘等)

缺点:

  • 可能产生大量重复计算(如朴素斐波那契递归)

  • 递归深度过大可能导致栈溢出

  • 效率通常低于迭代实现

递归优化技巧

  1. 记忆化(Memoization):存储已计算结果避免重复计算

    Map<TreeNode, Integer> memo = new HashMap<>();public int maxDepth(TreeNode root) {if (root == null) return 0;if (memo.containsKey(root)) return memo.get(root);int depth = Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;memo.put(root, depth);return depth;
    }
  2. 尾递归优化:某些编译器可以优化尾递归为迭代,减少栈空间使用

  3. 转换为迭代:使用栈或队列模拟递归过程

经典递归问题示例

  1. 阶乘计算

    int factorial(int n) {if (n == 1) return 1;          // 基准条件return n * factorial(n - 1);   // 递归条件
    }
  2. 斐波那契数列

    int fib(int n) {if (n <= 1) return n;                     // 基准条件return fib(n - 1) + fib(n - 2);          // 递归条件
    }
  3. 二叉树遍历(前序、中序、后序)

http://www.dtcms.com/a/330194.html

相关文章:

  • 18.10 SQuAD数据集实战:5步高效获取与预处理,BERT微调避坑指南
  • 数据分析可视化学习总结(美妆2)
  • Python解包技巧全解析
  • Python 基础语法(一)
  • 多处理器技术:并行计算的基石与架构演进
  • 疯狂星期四文案网第38天运营日记
  • 继《念念有词》后又一作品《双刃》开播 马来西亚新人演员业文Kevin挑战多面角色引期待
  • CF每日3题(1600)
  • element-ui 时间线(timeLine)内容分成左右两侧
  • npm run dev 的作用
  • Unity_2D动画
  • 游戏盾的安全作用
  • RK3568嵌入式音视频硬件编解码4K 60帧 rkmpp FFmpeg7.1 音视频开发
  • Celery+RabbitMQ+Redis
  • Traceroute命令使用大全:从原理到实战技巧
  • IPC Inter-Process Communication(进程间通信)
  • 2小时构建生产级AI项目:基于ViT的图像分类流水线(含数据清洗→模型解释→云API)(第十七章)
  • 基于Supervision工具库与YOLOv8模型的高效计算机视觉任务处理与实践
  • 1.Cursor快速入门与配置
  • Multisim的使用记录
  • GQA:从多头检查点训练广义多查询Transformer模型
  • 蒙以CourseMaker里面的录屏功能真的是完全免费的吗?
  • C#标签批量打印程序开发
  • Redis 键扫描优化:从 KEYS 到 SCAN 的优雅升级
  • Nginx Stream代理绕过网络隔离策略
  • 论文Review 激光SLAM VoxelMap | RAL 2022 港大MARS出品!| 经典平面特征体素激光SLAM
  • 第4节 Torchvision
  • MC0473连营阵图
  • 在线教程丨 Qwen-Image 刷新图像编辑 SOTA,实现精准中文渲染
  • Docker部署RAGFlow:开启Kibana查询ES数据指南