实习工资只发600元,你敢想吗?
600块实习工资,这已经不是“吃苦教育”了,这是拿人当免费劳动力试手感。原本说好2500,结果先给你砍到600多,下个月还只发1800,HR那边估计一句“系统算的”就想糊弄过去,听着都来火。
更离谱的是,前面刚裁了大半实习生,人都悬着,不转正还一拖几个月,工资居然还能少发。网友有人说,实习生的钱最容易被动,因为默认你不敢吭声;也有人说,很多公司就吃准了年轻人怕麻烦、怕得罪人。说白了,就是拿实习身份当软柿子捏。
但这事最气人的,不是穷,是你明明干了活,还得自己举证、自己催、自己找财务对线。截图一甩,对方才开始道歉补发。钱补回来了,恶心感补不回来。那种一边上班一边怀疑自己是不是又被坑的感觉,真挺伤人。
面试题:小行星碰撞
这题看着像模拟,真写起来,很多人会在“到底谁该爆掉”这里绕半天。
小行星一正一负,绝对值是大小。往右飞的写成正数,往左飞的写成负数。真正会撞上的,只有一种情况:前面那个往右,后面这个往左。别的组合你想得再热闹,也撞不上。
我一般看到这种题,第一反应不是写双层循环硬怼。那种写法能做,但味道不对。因为前面碰完了,后面还可能继续碰,天然就是个“回头看前一个”的过程,这种题用栈顺手。
比如:
[5, 10, -5]
先来 5,进栈。 10 也进栈。 -5 来了,就得跟栈顶 10 碰一下。结果 10 更大,-5 没了。
再比如:
[8, -8]
这就同归于尽。
还有一种最烦人的:
[10, 2, -5]
很多人这里会只碰一次,写完就交。其实不对。-5 先撞 2,2 没了;然后 -5 还得继续撞 10,最后 -5 也没了。这个“连续碰撞”才是这题真正的坑。
代码我按线上能看懂的写法来一版:
import java.util.ArrayDeque;
import java.util.Deque;
publicclassSolution{
publicint[] asteroidCollision(int[] asteroids) {
Deque<Integer> stack = new ArrayDeque<>();
for (int cur : asteroids) {
boolean alive = true;
while (alive && !stack.isEmpty() && stack.peekLast() > 0 && cur < 0) {
int top = stack.peekLast();
if (top < -cur) {
stack.pollLast(); // 栈顶炸了,当前小行星继续往前撞
continue;
}
if (top == -cur) {
stack.pollLast(); // 同归于尽
}
alive = false; // 当前小行星没了,或者同归于尽
}
if (alive) {
stack.addLast(cur);
}
}
int[] ans = newint[stack.size()];
int i = 0;
for (int n : stack) {
ans[i++] = n;
}
return ans;
}
}
这段代码里我觉得最关键的,不是栈本身,而是这个 while。
while (alive && !stack.isEmpty() && stack.peekLast() > 0 && cur < 0)
意思很直白:只要当前小行星还活着,栈里还有东西,并且栈顶向右、当前向左,那就继续撞。少了这个 while,[10, 2, -5] 这种连续碰撞就挂了。
时间复杂度是 O(n)。别一看里面有 while 就慌,每个小行星最多进栈一次、出栈一次,不会反复横跳。空间复杂度 O(n),最坏情况全都不碰撞,整个数组都进栈。
这题不难,难的是第一次写的时候容易把规则想复杂。其实就抓住一件事:只有“栈顶向右,当前向左”才会真的发生碰撞。 剩下的,全是按大小结算。 写顺了,这题就是一道很典型的栈模拟题。