月薪 3万但要 996 拼命,月薪1万却能朝九晚五生活规律,这两种工作你会怎么选?
月薪3万,换来的是996,消息回得比心跳还勤。月薪1万,朝九晚五,晚上能吃上热饭,周末还能像个人。这题看着像选工资,实际是在选命怎么花。
评论区也挺真实。有人说,年轻扛得住就先冲高薪,狠狠干几年,攒够了再撤。也有人直接回一句,钱是赚到了,人先废了,体检报告比工资条还吓人。
我偏后者。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),主要是这个栈。
这题写崩的人一般有两个地方。
一个是栈里存温度,不存下标。存温度你没法算间隔天数。 另一个是比较条件写错,题目要的是“更高温度”,所以必须是 >,不是 >=。相等不能出栈,这地方经常顺手写错。
单调栈这玩意,平时刷题看着玄,真到这题其实就很朴素: 前面一批人没找到答案,后面来一个更强的,能解决就当场解决,解决不了就继续压着等。
这题背下来没太大意义,记住这种判断顺序更值钱:遇到“下一个更大元素”、“第一个更高/更小”、“右边最近满足条件的位置”这类题,先别急着双循环,先想单调栈。
很多题,味道都差不多。