news 2026/10/2 20:38:10

【LeetCode Hot100】199.二叉树的右视图和56.合并区间

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【LeetCode Hot100】199.二叉树的右视图和56.合并区间

【LeetCode Hot100】199.二叉树的右视图和56.合并区间

摘要

这篇文章用来记录我在练习 hot100 中题号199和题号56的做题过程。

199. 二叉树的右视图

先来看199题——二叉树的右视图。题目见下图:

第一次思路

我第一次的做题思路是既然我们是要右视图,那么道理很简单,我们就尽量沿着右边的子树右孩子和左边子树的右孩子一直往下深度遍历不就好了?

所以我创建了两个数组lList和rList分别存储左子树和右子树的遍历结果,再比较List大小,rList大,那就直接返回,lList大,就截取lList中超过rList的部分,拼接到rList上。当时自我感觉非常符合右视图,因为我的做法是一直优先找右孩子。

第一次错误题解

我的第一次错误题解见下文:

classSolution{List<Integer>rList=newArrayList<Integer>();List<Integer>lList=newArrayList<Integer>();publicList<Integer>rightSideView(TreeNoderoot){if(root==null){returnnewArrayList<Integer>();}//保存右遍历结果rList.add(root.val);//保存左遍历结果lList.add(root.val);ldfs(root.left);rdfs(root.right);if(rList.size()>=lList.size()){returnrList;}else{for(inti=rList.size();i<lList.size();i++){rList.add(lList.get(i));}returnrList;}}//优先找左子树的右孩子publicvoidldfs(TreeNoderoot){if(root!=null){lList.add(root.val);//只要右孩子不为空就走右孩子if(root.right!=null){ldfs(root.right);}else{ldfs(root.left);}}}//优先找右子树的右孩子publicvoidrdfs(TreeNoderoot){if(root!=null){rList.add(root.val);//只要右孩子不为空就走右孩子if(root.right!=null){rdfs(root.right);}else{rdfs(root.left);}}}}

测试结果与反例

这个做法在进行简单的运行测试的时候成功通过,在最后提交时判错。因为测试用例正巧碰上了当前思路的巧合:整个左右子树都是右孩子多于或等于左孩子,或者是右孩子没有只能找左孩子。我们来看几个巧合:

图1:2子树只有右孩子
图2:2子树只有左孩子但是没有右孩子

那不满足巧合的呢?

很明显,我们策略是右孩子不为空就走右孩子,那走到节点2,就去节点5了。哎嘿,没错,到这里结束了。。。下面右视图也能看到的6节点和7节点根本没走到,所以这个做法是错的。

正确做法

那我们再来看看正确的做法,也是一样的思想,优先找右边的孩子。但这次不是走右孩子之后,左孩子不管了。简要的思路还是使用深度遍历,在遍历过程中维护一个深度变量depth,当我们找到同一层节点最右边的孩子时,保存到结果List中同时深度变量depth加1,此时深度遍历同一层其他孩子那里时,发现depth== List.size(); 时,说明在这一层中,右视图能看到的节点已经找到了,这个节点就不用保存了,我们继续往下走就可以了。

代码参考:

class Solution { List<Integer> ans = new ArrayList<>(); public List<Integer> rightSideView(TreeNode root) { dfs(root, 0); return ans; } public void dfs(TreeNode root, int depth) { if (root == null) { return; } if (depth == ans.size()) { ans.add(root.val); } dfs(root.right, depth + 1); dfs(root.left, depth + 1); } }

56. 合并区间

我们再来看第二个题目,56题:合并区间。题目见下图:

思路

在初次看到这个题时,很容易想到那依旧暴力for循环。我们先固定一个区间,然后遍历其他所有区间找到可以合并的。但我们仔细观察就会想到,我们在合并两个区间的时候,往往最先看的是区间A的右边界与区间B的左边界相比,再看区间A的右边界与区间B的右边界相比。那我们是不是可以先把数组按照左边界的大小先排个序呢?这样我们在比较的时候不就只用看相邻两个区间了吗?而且只用看左区间右边界和右区间左边界的关系就好了。

那数组排序呢?我们可以直接用Arrays提供的sort()函数,自定义一下Comparator的比较规则就可以非常简单的实现。

实现代码

按照这个思路,我们就不需要再用for循环从头找到尾,费时费力的解决了,下面看实现代码:

class Solution { public int[][] merge(int[][] intervals) { if(intervals.length == 0){ return new int[0][2]; } Arrays.sort(intervals, new Comparator<int[]>(){ public int compare(int[] interval1,int[] interval2){ //按照左边界做升序排列 return interval1[0] - interval2[0]; } }); //保存最终结果 List<int[]> ans = new ArrayList<int[]>(); for(int i = 0; i < intervals.length; ++i){ //当前区间左边界 int l = intervals[i][0]; //当前区间右边界 int r = intervals[i][1]; // 1.ans中还没有合并后的区间以及不需要合并的区间结果 // 2.当前区间左边界和ans中最新结果的右边界比较,因为当前区间一定排序在ans中已使用过的所有区间的右边 if(ans.size() == 0 || ans.get(ans.size() - 1)[1] < l){ // 1.ans中还没有区间结果 // 2.当前区间不需要进行合并 ans.add(new int[]{l,r}); } //当前区间左边界和ans中最新结果的右边界比较之后发现可以合并 else{ //这里取两个区间的右边界最大值是因为可能出现这种情况 [1,6],[2,3] ans.get(ans.size() - 1)[1] = Math.max(ans.get(ans.size() - 1)[1], r); } } //别忘了题目要求的返回值类型是二维数组 return ans.toArray(new int[ans.size()][]); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 20:37:07

Superpowers实战:为Codex CLI构建规划记忆与审查的AI协作层

你用过Codex CLI吗&#xff1f;如果你和我一样&#xff0c;花了几周时间让它处理真实项目&#xff0c;大概率会碰到同一个尴尬&#xff1a;小任务很惊艳&#xff0c;一旦涉及多文件修改、跨模块重构、需要遵守项目里既有约定时&#xff0c;它就变成一个“健忘的天才”——上下文…

作者头像 李华
网站建设 2026/10/2 20:35:38

UART通信详解:从物理层电平到STM32 HAL库配置与调试实战

UART在我眼里一直是通信协议里最“亲民”的那个。它只有两根数据线&#xff0c;没有时钟线&#xff0c;协议帧结构简单到看一眼就能记住&#xff0c;可它承载了无数嵌入式设备从调试到量产的全过程。我最早接触单片机就是从点亮LED和printf重定向开始的&#xff0c;而那个print…

作者头像 李华
网站建设 2026/10/2 20:34:57

System Prompt 膨胀:你的 AI 有多少预算给了“自我介绍“?

&#x1f44b; Hi&#xff0c;带娃的我热爱 AI 大模型应用落地、意识解码与 AI 开发工具链 。 &#x1f4a1; 创业路上&#xff0c;用技术换时间&#xff0c;一起把 AI 变成生产力 &#x1f680; >System Prompt 膨胀&#xff1a;你的 AI 有多少预算给了"自我介绍"…

作者头像 李华
网站建设 2026/10/2 20:34:37

对象存储服务器vs数据库

一、先看结论图片可以存进普通数据库&#xff0c;但代价极高&#xff0c;几乎没人这么做。原因不是“技术上做不到”&#xff0c;而是数据库的设计目标与图片的存储需求根本不匹配。二、普通数据库 vs 对象存储&#xff1a;设计目标完全不同维度普通数据库&#xff08;MySQL&am…

作者头像 李华
网站建设 2026/10/2 20:31:07

STM32定时器本质:时钟脉冲计数与时间基准推导

1. 这不是“数秒”&#xff0c;而是数“时钟脉冲”&#xff1a;STM32定时器的本质真相你写过HAL_Delay(1000)&#xff0c;也配置过TIM2的PWM输出&#xff0c;甚至用过输入捕获测过超声波回波时间——但有没有哪一刻&#xff0c;你盯着CubeMX里那个“Prescaler”和“Counter Per…

作者头像 李华
网站建设 2026/10/2 20:30:19

大模型API价格目录开源:从计费建模到成本对比的工程实践

1. 从“查价查到头大”说起&#xff1a;这个开源目录到底解决了什么国内大模型 API 的价格&#xff0c;是我最近半年被问得最多的问题之一。不是“哪个模型最强”这种主观题&#xff0c;而是非常具体的&#xff1a;“DeepSeek 现在多少钱一百万 token&#xff1f;”“智谱和通义…

作者头像 李华