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

543刷题记录

543. 二叉树的直径

你提供的这个写法非常棒,它不仅是正确的,而且是解决这个问题的最优解法之一,时间复杂度为 O(N),N 是节点的数量。

这是一种非常精妙的“一次遍历”解法,它在一次深度优先搜索(DFS)中同时完成了两项任务。我们来详细分析一下它为什么是正确的。

核心思想:函数的多重职责

这个算法的核心在于 dfs 这个递归函数。它被设计用来同时做两件事:

  1. [返回值]: dfs(node) 返回node 为起点的、向下延伸的最长路径长度(边数)。我们称这个为 node 的“最大深度”或“最大链长”。

  2. [副作用]: dfs(node) 在执行过程中,会顺便计算node 为“转折点”的直径,并用这个值去更新全局(在C++中是被lambda捕获)的 ans 变量。

逐行代码分析

C++

class Solution {
public:int diameterOfBinaryTree(TreeNode* root) {// 1. 'ans' : // 这是我们的“全局”最大直径。// [&] 捕获允许 dfs lambda 修改它。int ans = 0; // 2. 'dfs' lambda:// C++23 风格的递归 lambda。// auto&& dfs 是为了让 lambda 内部可以调用自己。// '-> int' 指明了返回类型是 int。auto dfs = [&](this auto&& dfs, TreeNode* node) -> int {// 3. 基础情况 (Base Case):// if (node == nullptr) { return -1; }// 这是整个算法最精妙的地方。// 为什么返回 -1?// 考虑一个叶子节点(leaf),它的左右孩子都是 nullptr。// 当它计算 l_len 时,会调用 dfs(nullptr),返回 -1。// 然后 l_len = -1 + 1 = 0。// 这完全正确:一个叶子节点,它向左下方延伸的最长链长是 0。// 这个 -1 是一个“哨兵值”,它使得 +1 运算对于空节点和叶子节点都能完美生效。if (node == nullptr) {return -1; }// 4. 递归计算 (后序遍历)// int l_len = dfs(node->left) + 1;// int r_len = dfs(node->right) + 1;// 我们来分析 l_len:// - dfs(node->left) 返回了左子树的“最大链长”。// - +1 加上了从 'node' 到 'node->left' 的这条边。// - 所以, 'l_len' = 从 'node' 出发,向左下方延伸的最长路径长度。// 例子:// - 如果 node->left 是 nullptr, dfs(nullptr)返回-1, l_len = -1 + 1 = 0。 (正确)// - 如果 node->left 是叶子, dfs(leaf)返回0, l_len = 0 + 1 = 1。  (正确)int l_len = dfs(node->left) + 1; int r_len = dfs(node->right) + 1;// 5. [副作用]:更新全局最大直径// ans = max(ans, l_len + r_len);// 这是解题的核心。// 在当前节点 'node',我们已经知道了:// - l_len: 向左的最长链// - r_len: 向右的最长链// 如果最长路径以 'node' 为“转折点”,那么这条路径的长度就是 l_len + r_len。// 我们用这个“以node为中心的直径”去和已经找到的“全局最大直径 ans”比较,// 并更新 ans。// 注意:真正的直径可能并不经过 'root',它可能完全在某个子树中。// 但因为我们对 *每个节点* 都执行这个操作,所以我们一定会找到那个// 真正的“转折点”并计算出正确的最大值。ans = max(ans, l_len + r_len);// 6. [返回值]:返回当前节点的最大链长// return max(l_len, r_len);// 这一步是为了 'node' 的父节点准备的。// 'node' 的父节点并不关心“以node为转折点的直径”(l_len + r_len)。// 'node' 的父节点只关心:“如果我把 'node' 作为我的路径的一部分,// 我能向下延伸多远?”// 答案是:取 'node' 向左和向右中较长的那一条链。// 所以我们返回 max(l_len, r_len)。return max(l_len, r_len); };// 7. 启动 DFSdfs(root);// 8. 返回结果// 经过 dfs(root) 的调用,ans 已经被(通过副作用)// 更新为整棵树中所有节点计算出的 (l_len + r_len) 的最大值。return ans;}
};

总结

这个写法是正确的,因为它巧妙地利用了递归的返回值副作用

  • 返回值 max(l_len, r_len):用于向上传递“深度”信息,供父节点计算它自己l_len/r_len

  • 副作用 ans = max(ans, l_len + r_len):用于在当前节点结合左右子树信息,计算“以当前节点为中心的直径”,并更新全局答案。

return -1 的基础情况是让这一切数学关系(+1)得以自洽的关键。

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

相关文章:

  • 上海门户网站建设公司logo在线
  • 【FPGA】三八译码器——仿真验证
  • 哪些网站可以做设计方案网站建设 客户
  • h5游戏免费下载:堆雪人
  • UltraISO制作系统启动盘
  • 未来之窗昭和仙君(三十六)抽奖随机算法前端——东方仙盟筑基期
  • wordpress网站添加密码访问17网站一起做网店广
  • 惠州网站建设制作志愿服务网站建设中标公告
  • 资料分析-年均与乘积增长率
  • 视频网站用什么做的济南网站建设山东聚搜网推荐
  • Minecraft合集
  • 公司网页网站建设sae wordpress 图片
  • 网站建设读后感为什么网页不能打开建设银行网站
  • 百度网站流量查询南京房地产网站建设
  • 南安梅山建设银行网站长春快速建站模板
  • CSMA/CA 协议和CSMA/CD的区别
  • 网络自动化:Ansible/Netmiko 网络设备批量配置与管理
  • 探索聊天机器人系统提示的秘密[特殊字符]
  • 接近光速运动下的光速不变性:基于张祥前统一场论的推导与验证
  • 固始网站制作四川德充建设集团有限公司网站
  • STM32G474单片机开发入门(二十七)HRTIME高精度定时器的PWM(50KHZ)输出实战
  • Windows磁盘占用率高解决记录
  • 泛用性而言,系统分析师 与 信息系统项目管理工程师 比较
  • 网站程序国内 wordpress主题
  • 太仓公司网站建设电话天津企业网站建设方案
  • AI 浏览器技术趋势分析:Perplexity Comet 的创新与早期用户激励机制探讨
  • 4.基础开发工具(一)
  • 网站如何调用微博wordpress 发布视频
  • SQL注入第一步:数据库类型判断
  • 软件架构师个人总结笔记