程序员老鬼

朋友从某节跑路了,说强度太大了,早上10点,晚上10点。去了才不到三星期,不知道她有没有被拉黑简历

刚看到个贴子,说有姑娘从字节跑路了,早十晚十扛不住,干了不到三周就溜了,还在担心自己会不会被拉黑简历。

Image

网友回帖两派,一派说“才三星期就怂了”,觉得她玻璃心;另一派说“人不是电池”,加班强度这么大,走人很正常。

我觉得这事吧,先别急着嘲笑谁。有人适合大厂高压换高薪,有人就适合强度低点、睡得着觉的生活,本来就没标准答案。真要说问题,就是很多人进大厂前只看工资和名头,没认真算过这份钱背后要付出的时间和精力。

换个角度想,就算真被拉黑了,也只是少了一家选择,不是被全行业封杀。认清自己能承受的强度,勇敢止损,比硬撑到身心垮掉强多了。

面试题:最大层内元素和

昨晚十一点多我刚躺下准备刷会儿视频,我们组那个小李突然在群里@我:“东哥,面试碰到个二叉树题,最大层内元素和,你咋写?”我人都快睡着了,只能爬起来拿起电脑,顺嘴跟他唠了半天。

这个题大概意思你们应该都见过:给你一棵二叉树,每一层节点都有若干整数值,把每一层的值加起来,看哪一层的总和最大,返回这一层的编号(一般是从 1 开始数根节点那层)。比如说,根节点这一层和是 5,下一层和是 7,再下一层和是 10,那就返回 3。

听起来挺生活化的,对吧,就好像数一下公司每一层楼有多少人,然后看哪一层最挤。

我当时跟小李说,这种题其实就两条路,要么深度优先(DFS)往下钻的时候顺便把“当前是第几层”带着,把每一层的和记录到一个数组里;要么干脆用广度优先(BFS),一层一层地扫,这个更符合人脑对“层”的直觉。面试的时候一般 BFS 更好讲一点。

我给他敲的代码是 BFS 版本,大概长这样(Java 写的哈):

// LeetCode 上常见的二叉树节点定义
classTreeNode{
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;
    }
}

publicclassSolution{

publicintmaxLevelSum(TreeNode root){
if (root == null) {
return0; // 看具体题目要求,有的不会给空树
        }

        java.util.Queue<TreeNode> queue = new java.util.LinkedList<>();
        queue.offer(root);

int currentLevel = 0;    // 当前层从 1 开始数
int bestLevel = 1;       // 答案层
long bestSum = Long.MIN_VALUE; // 防止 int 溢出,保险一点

while (!queue.isEmpty()) {
int size = queue.size();  // 这一层有多少节点
            currentLevel++;
long levelSum = 0;

// 把这一层的节点都处理完
for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                levelSum += node.val;

if (node.left != null) {
                    queue.offer(node.left);
                }
if (node.right != null) {
                    queue.offer(node.right);
                }
            }

// 更新最大和和对应层号
if (levelSum > bestSum) {
                bestSum = levelSum;
                bestLevel = currentLevel;
            }
        }

return bestLevel;
    }
}

当时我边讲边哈欠,你们简单感受一下这个流程哈:

先丢一个根节点到队列里,队列就好比电梯,哪一层的人全进电梯,我们就把这层所有人点名一遍(那就是 for 循环里那一坨),把他们工资加起来(levelSum += node.val),顺便把他们的左右孩子塞电梯里,准备下一层。每搞完一层,就看一下这一层的总和是不是目前最大的,是的话记一下“最好的一层是谁”。

这一整套遍历下来,每个节点只进队、出队一次,所以时间复杂度就是 O(N),空间就是队列那点东西,最坏情况一层特别宽,就是 O(N),一般面试官听你说到这儿就不会再追问了。

小李当时问了一句:“那 DFS 能不能写?”当然能啊,不过 DFS 写法就是换个姿势而已。脑子里记住一个“层号 -> 层和”的映射,比如用 List<Integer> 或 Map<Integer, Long>,递归的时候把当前层传下去:

publicclassSolutionDfs{

publicintmaxLevelSum(TreeNode root){
        java.util.List<Long> sums = new java.util.ArrayList<>();
        dfs(root, 0, sums); // 从第 0 层开始,等会儿返回的时候 +1 就行

long best = Long.MIN_VALUE;
int bestLevel = 0;
for (int i = 0; i < sums.size(); i++) {
if (sums.get(i) > best) {
                best = sums.get(i);
                bestLevel = i + 1; // 题目里层数从 1 开始
            }
        }
return bestLevel;
    }

privatevoiddfs(TreeNode node, int level, java.util.List<Long> sums){
if (node == null) {
return;
        }
if (level == sums.size()) {
            sums.add(0L);
        }
        sums.set(level, sums.get(level) + node.val);

        dfs(node.left, level + 1, sums);
        dfs(node.right, level + 1, sums);
    }
}

这个就像是在一条小路上一路往下走,每到一个深度你都顺手在“这一层的累计和”上加一下,走完整棵树再回头找哪一层最大。思路不难,就是递归多了栈空间开销,理论上最坏情况链表型的树会到 O(N)。

顺便插一句,我之前写数据库性能那篇对比文章的时候也用过类似“分层统计”的思路,只不过那会儿按的是 QPS 区间,不是树的层数,底层逻辑其实挺像:先分桶,再在桶里算最大值。

反正这个题你只要把“层序遍历”和“顺便求和”这两个词挂嘴边,代码像上面这样别写出什么离谱的 bug,面试官一般会点点头,然后开始问你别的坑了。

好了我不说了,我去给小李催简历进度了,你要是哪天被问到这题,记得想起我半夜起床讲算法这回事就行。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领,也可以链接我微信:hls404