39岁被大厂裁员,直接躺平不上班了!靠老婆6000元工资过日子,比以前舒服百倍。
39岁被大厂一刀裁了,月薪两万多的程序员,转头直接不卷了。不上班,接送孩子,买菜做饭,家里主要收入变成老婆那6000块。离谱吧?更离谱的是,他自己说现在比以前舒服百倍。
评论区也挺真实。有人说这不叫躺平,这叫终于活过来了。还有人酸,说前面肯定攒够了,不然谁敢这么玩。可你仔细想想,大厂那点工资,很多时候真是拿命换的。白天开会,晚上改bug,周末还得装在线,钱是多一点,人也跟被榨干差不多。
最扎心的是,很多人嘴上笑他“吃老婆软饭”,心里其实羡慕得要命。能从工位上撤下来,回家闻点油烟味,接孩子放学,居然成了奢侈品。
面试题:寻找重复数
数组长度是 n + 1,数字都落在 1 ~ n,只允许找那个重复数,题目还顺手把路堵死了:**不能改原数组,额外空间还得是 O(1)**。 这种题我第一眼一般不信哈希表。能做,但八成不是出题人想看的东西。真正别扭的点在这:它明明是数组题,解法却更像链表题。
先看最笨的写法,很多人面试时一紧张就这么落了:
publicintfindDuplicate(int[] nums){
Set<Integer> seen = new HashSet<>();
for (int x : nums) {
if (!seen.add(x)) {
return x;
}
}
return -1;
}
能过,大概率也能拿点分,但空间 O(n),题目条件没守住。 这题更像是在考你能不能把下标和数值“串起来”看。
比如数组是:
int[] nums = {1, 3, 4, 2, 2};
下标 0 走到 nums[0]=1,再走到 nums[1]=3,再到 nums[3]=2,再到 nums[2]=4,再到 nums[4]=2。 看到没,走着走着绕回去了。只要有重复数,这条路径里就会形成环。
所以直接上快慢指针。
publicclassSolution{
publicintfindDuplicate(int[] nums){
int slow = nums[0];
int fast = nums[0];
do {
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow != fast);
int p1 = nums[0];
int p2 = slow;
while (p1 != p2) {
p1 = nums[p1];
p2 = nums[p2];
}
return p1;
}
}
这段代码别死背,抓两个判断就够了。
第一,为什么一定有环? 因为总共有 n + 1 个位置,但值只能落在 1 ~ n,可去的目标点只有 n 个。位置多,目标少,按抽屉原理,迟早撞车。
第二,为什么相遇后再各走一步,最后会在重复数那里碰头? 这个就和链表找环入口是一个套路。数组里的“重复值”,本质上就是那个环入口。
这题容易写错的地方也挺集中:
// 容易错:把起点写成 0,然后循环里又直接 slow = nums[slow]
int slow = 0;
int fast = 0;
不是不能做,是你后面一旦边界没想清楚,很容易把入口推导绕晕。我更喜欢直接从 nums[0] 起步,代码短一点,也不容易把自己写迷糊。
再说一句,面试里这题不是考你会不会背“弗洛伊德判圈法”这几个字,没啥用。人家真正想看的是: 你能不能从“重复元素”想到“映射关系”,再从“映射关系”想到“环”。
想到这一步,这题就过了。想不到,就会一直在排序、哈希、标记数组里打转。 这就是这题最坏的地方。看着像数组,实际上拐着弯考思路。