程序员老鬼

月薪 3万但要 996 拼命,月薪1万却能朝九晚五生活规律,这两种工作你会怎么选?

月薪3万,换来的是996,消息回得比心跳还勤。月薪1万,朝九晚五,晚上能吃上热饭,周末还能像个人。这题看着像选工资,实际是在选命怎么花。

Image

评论区也挺真实。有人说,年轻扛得住就先冲高薪,狠狠干几年,攒够了再撤。也有人直接回一句,钱是赚到了,人先废了,体检报告比工资条还吓人。

我偏后者。3万听着很猛,但你得先有空花。天天加班到脑子发木,周一盼周五,周五回家只想躺尸,这钱赚着就有点像“高级耗材”。1万当然不算轻松发财,可起码日子是自己的。能睡觉,能吃饭,能见人,情绪没那么容易炸,很多时候这才是真正的“到手收入”

面试题:每日温度

栈里压着一串温度,很多人第一次看到“每日温度”这题,第一反应就是双重循环:拿今天的温度,往后一个个比,碰到更高的就停。能做,对拍也能过小样例,但数据一大就开始磨机器了。

这题我第一眼不太信暴力。因为它其实不是在找“最大值”,也不是排序,核心就一句:当前这一天,什么时候能等到第一个更高温度。这种“只关心后面第一个更大元素”的味道,基本就该往单调栈上靠了。

先看最笨的写法,逻辑没问题,就是慢:

publicint[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] ans = newint[n];
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (temperatures[j] > temperatures[i]) {
                ans[i] = j - i;
break;
            }
        }
    }
return ans;
}

问题就在这里。比如后面一长段递减温度,前面的元素会反复扫,很多比较其实都白干了。

这题更顺手的做法,是栈里存“还没等到更高温度的下标”,并且让这些下标对应的温度保持单调递减。新温度一来,谁比它低,谁就可以出栈结账。

import java.util.ArrayDeque;
import java.util.Deque;

publicclassSolution{
publicint[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] ans = newint[n];
        Deque<Integer> stack = new ArrayDeque<>();

for (int i = 0; i < n; i++) {
while (!stack.isEmpty() 
                    && temperatures[i] > temperatures[stack.peek()]) {
int prev = stack.pop();
                ans[prev] = i - prev;
            }
            stack.push(i);
        }
return ans;
    }
}

举个过程,73,74,75,71,69,72,76,73。

扫到 74 时,发现它比栈顶 73 大,那说明第 0 天终于等到了更高温度,答案就是 1。 扫到 72 时,会连续弹出 69 和 71,因为这俩等的就是今天。 扫到 76 时,前面压着的一串没解决的下标基本都会被清掉。

这个过程有个很关键的点:每个下标只会入栈一次、出栈一次。所以总时间复杂度不是看起来的嵌套循环,而是 O(n)。空间复杂度 O(n),主要是这个栈。

这题写崩的人一般有两个地方。

一个是栈里存温度,不存下标。存温度你没法算间隔天数。 另一个是比较条件写错,题目要的是“更高温度”,所以必须是 >,不是 >=。相等不能出栈,这地方经常顺手写错。

单调栈这玩意,平时刷题看着玄,真到这题其实就很朴素: 前面一批人没找到答案,后面来一个更强的,能解决就当场解决,解决不了就继续压着等。

这题背下来没太大意义,记住这种判断顺序更值钱:遇到“下一个更大元素”、“第一个更高/更小”、“右边最近满足条件的位置”这类题,先别急着双循环,先想单调栈。

很多题,味道都差不多。