最近又看到一个事儿,西安某科技公司的领导晚上十点多在工作群里发飙了!原因竟然是没人回复他发的信息。
这位领导是怎么发飙的?先是一个字一个字打出“你们到底都在干嘛?”然后又用一串大写字母疯狂输出,最后还给大家安排了个加班任务。
谁都知道,晚上十点了,大家能不回复消息就不回复了,早就在自己沙发上准备抱着手机看剧或者撸猫了,能不管工作群里的信息就不管嘛。
你发的这个通知又不紧急,也没什么不得不处理的事儿,凭什么强迫大家立马回应?
反正我觉得,如果我是那个员工,看到这种信息,我也会把手机丢一边,然后去睡觉。毕竟,这种通知完全不重要,第二天早晨面对面说清楚多好。
我还看到有网友说“找个大一点的公司,遇到的人素质会高一些”。这种话说得也挺对,谁能忍受这种没有边界的工作呢?老板如果半夜都开始加班,估计这公司是真的快不行了吧😅
所以,大家也不用太焦虑,毕竟,工作和生活的平衡,永远比加班更重要。
算法题:根据身高重建队列
最近看了一道有意思的算法题,想和大家一起聊聊。
题目是这样的:找树的左下角的值。听起来是不是有点像科幻小说的标题?不过没关系,这其实就是给你一棵二叉树,让你找出最左边的底层节点的值,简单明了。
刚开始我看到这道题的时候,心里也在想:哎,这个题目咋跟我平常做的树遍历有点像呢?只不过要关注的是最左边的节点。我们都知道二叉树遍历的方式有很多,常见的有前序、中序、后序遍历,还有层序遍历。而在这道题中,显然层序遍历更合适一点。因为我们要找的是最底层的最左边的那个节点,显然按层次一层一层遍历最直观。
好了,问题有了,接下来就是如何解决它。
首先,我们可以使用一个队列(Queue),这是层序遍历中常用的数据结构。你可以把每一层的节点依次加入队列,然后遍历整个树,最后返回最左边的那个节点。
来,直接上代码:
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
public int findBottomLeftValue(TreeNode root) {
if (root == null) {
return -1; // 根节点为空,直接返回
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root); // 将根节点加入队列
int leftMostValue = 0;
while (!queue.isEmpty()) {
int size = queue.size(); // 当前层的节点数
// 遍历当前层的所有节点
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll(); // 取出队首元素
// 只在当前层的第一个节点时更新最左边的节点值
if (i == 0) {
leftMostValue = node.val;
}
// 如果左子节点存在,将左子节点加入队列
if (node.left != null) {
queue.offer(node.left);
}
// 如果右子节点存在,将右子节点加入队列
if (node.right != null) {
queue.offer(node.right);
}
}
}
return leftMostValue;
}
}
这里的核心思路就是:每一层遍历完,最先加入队列的节点就是这一层的最左边的节点。层序遍历每遍历一层,我们就更新一次最左边的节点,直到遍历完最后一层。
代码不长,逻辑也很简单。不过这道题目让我又想起了一个有趣的事情——每次遇到这种“找最左节点”或“最右节点”的题目,心里都会有一种莫名的成就感,仿佛在做一件很聪明的事,明明是层序遍历这么简单的操作,为什么别人想不到呢?其实,很多时候就是细节决定了效率和简洁度。
那我为什么要提到细节呢?因为很多时候程序员容易陷入一个误区,就是觉得遍历树总是得从根节点开始,或者必须做深度优先搜索(DFS)。其实在处理这类问题时,层序遍历的效果往往更好。
当然,树的结构和节点的排列会影响我们思考的方式,比如如果树的高度特别高,层数特别多,深度优先搜索可能需要考虑栈的溢出问题,而层序遍历则没有这个烦恼。
其实从算法的角度来看,层序遍历(广度优先搜索,BFS)是非常直观和高效的,尤其在查找树的某一层节点时,BFS的优势尤为明显。而深度优先搜索(DFS),尤其是递归方式,可能会导致很多不必要的栈调用,尤其是当树非常深时。
好吧,别说了,感觉自己又像个算法科普小达人了😂。回到这道题目,其实就是要在每一层的遍历中找出最左边的节点,我们保证通过层序遍历每一层的第一个节点就是最左节点,所以这样做时间复杂度是O(n),其中n是树中节点的总数。空间复杂度是O(w),其中w是树的最大宽度,也就是层序遍历队列中节点的最大数量。
如果再细想一下,层序遍历有时候也能非常好地利用队列的特性。队列的先进先出(FIFO)特性可以帮我们在每一层遍历中很清楚地识别出最左边的节点,避免了深度优先遍历中对节点的重复计算。
总之,这道题目的核心思路就是:利用层序遍历来逐层检查,并且每次只保留最左边的节点值,直到最后一层。
-END-
以上,就是今天的分享了,看完文章记得右下角给何老师点赞,也欢迎在评论区写下你的留言。