程序员老鬼

985大厂被裁员工,年近 30,21年计算机毕业,近期被裁,思来想去真不知道应该何去何从~

这哥们不是没路,是一下子被裁懵了。

985、计算机、21年毕业、在北京混了几年,还有户口,手里一百多万存款,家里还能托底两百个。你说惨吧,跟普通打工人比,真不算惨;你说不慌吧,快三十了被大厂一脚踢出来,没对象没家庭,也没别的手艺,心里空一下太正常了。

Image

我觉得最别急着做“大决定”。什么放弃北漂、回老家、转行、躺平,这些都先别上头。先休一阵,把简历投起来,看看市场到底给不给你饭吃。北京户口这东西,真不是说扔就扔的。

你不是卷王,也不代表没活路。大厂混过几年,至少简历还能打。先找个能续命的坑,钱别乱动,别一失业就开始怀疑整个人生。世界不属于你也没事,先把下个月属于谁搞明白。

面试题:镜面反射

光从左下角打出去,题目没让你模拟反弹。

这题叫「镜面反射」,但真按镜子一下一下反弹去写,基本就是自己给自己挖坑。坐标会绕,方向会变,边界还容易写出一堆 if。第一眼我就不太信这种模拟解,尤其是 p、q 一大,代码看着能跑,心里其实没底。

更稳的看法是:别让光反弹,把房间复制出去。

原来光碰到墙会反射。我们换个角度,把墙外面再贴一个同样的房间,光就不用拐弯了,直接沿直线往前走。

比如房间边长是 p,激光每走一间房的宽度,竖直方向上升 q。什么时候能碰到某个接收器?就是竖直方向累计高度,刚好是 p 的整数倍。

也就是找一个最小的次数 k:

k * q 是 p 的倍数

不过代码里没必要真算最小公倍数。这个题最后只关心一件事:p 和 q 去掉共同的 2 之后,谁是偶数。

我一般会这么写,不绕。

classSolution{
publicintmirrorReflection(int p, int q){
while ((p & 1) == 0 && (q & 1) == 0) {
            p >>= 1;
            q >>= 1;
        }

if ((p & 1) == 0) {
return2;
        }

if ((q & 1) == 0) {
return0;
        }

return1;
    }
}

这里最容易卡的不是代码,是返回值为什么这么判。

把 p 和 q 同时除以 2,其实是在消掉「两个方向都翻倍」的部分。比如 p=6,q=4,真正影响落点的不是 6 和 4,而是 3 和 2。共同的 2 消掉以后,光线最后撞到哪边,奇偶性就够用了。

剩下三种情况:

p 是偶数,q 是奇数,返回 2。

q 是偶数,p 是奇数,返回 0。

p 和 q 都是奇数,返回 1。

有些人会写 gcd 或 lcm,也行,但这题用位运算除 2 更干净。不是为了炫技,是因为它刚好只需要处理 2 的因子。

换成 gcd 写法大概这样:

classSolution{
publicintmirrorReflection(int p, int q){
int d = gcd(p, q);
        p /= d;
        q /= d;

if ((p & 1) == 0) {
return2;
        }

if ((q & 1) == 0) {
return0;
        }

return1;
    }

privateintgcd(int a, int b){
while (b != 0) {
int t = a % b;
            a = b;
            b = t;
        }
return a;
    }
}

但我更偏向第一种。原因很简单:题目最后判断的是奇偶,不是最大公约数本身。你把所有公因子都约掉当然没问题,但只消 2 的因子也够了。

拿几个例子扫一下:

p = 2, q = 1
p 偶,q 奇,返回 2

p = 3, q = 1
p 奇,q 奇,返回 1

p = 4, q = 2
先同时除 2,变成 p = 2, q = 1,返回 2

这题别被「反射」两个字带偏。题目给的是几何,最后落到代码里,其实就是约掉共同的 2,然后看奇偶。

真去模拟光线反弹,也能做,但没必要。算法题里最怕这种代码:看起来很努力,实际把简单问题写复杂了。