程序员老鬼

同事被优化了,赔了N+1,找了三个月工作没有结果,刚刚知道他竟然去了蚂蚁,年包40多万,还涨了 30%~

刚看到个贴子,说楼主同事9 月被优化,拿了补偿后失业三个月,一直投简历没动静,楼主还替她捏把汗。

结果今天人家发朋友圈,直接去蚂蚁上岸,年包四十多万,比之前多了三成,楼主也直呼羡慕。

Image

网友评论我也瞄了下,有人说“被裁就是天降好运”“早知道我也想被优化”。我觉得这就有点想多了。结果是爽的,但别忘了过程有多煎熬:收入不稳定、面试被拒、身份从“在职”变成“待业”,这些情绪都得自己扛。

有准备的人,刚好撞上了运气。底层能力、人脉、心态稳不稳,都是能不能接住机会的关键。羡慕别人的 offer 没问题,但别只会感叹,多花点时间提升自己。

面试题:逃脱阻碍者

那天晚上十一点多,我在公司楼下便利店等微波炉叮泡面,手机上刷到一道题,名字起得特别中二——“逃脱阻碍者”。我脑子里立马就自动补画面:我一个小码农,在工位上被一堆 Bug 围追堵截,看谁先冲到下班那一刻的地铁站 😂

其实题目大概意思是这样的:

一、小故事版题意

你现在在二维平面上的原点 (0, 0),目标是跑到一个终点,比如 (x, y)。 有一堆“阻碍者”(可以理解成怪物、保安、前任…随便),一开始散落在平面上的不同坐标。

规则很简单:

  • 你和阻碍者移动速度完全一样,每一步可以往上下左右走一格。
  • 谁如果在某个时刻,跟你站到同一个坐标上,你就算被抓住,逃脱失败。
  • 问:你有没有可能成功先到终点,而且中途不被抓?

输入大概就是:

int[][] ghosts = { {1, 0}, {2, 2} }; // 阻碍者坐标
int[] target = {3, 4};               // 终点坐标

要返回一个 boolean:能不能跑。

二、为啥这题其实只是一道“谁离终点近”的题

刚看到会下意识想:是不是要模拟移动、BFS、算路径啥的? 结果想了两分钟:完全不用。

关键点就一句话:大家速度一样,走的也是同一套路(上下左右一步一格),那谁更接近终点,谁就更占优势。

在这种规则下,有一个很关键的距离概念:曼哈顿距离。

对一个点 (a, b) 到 (c, d) 的最少步数,就是:

|a - c| + |b - d|

因为你每一步,只能在 x 或 y 方向走 1 格,想象一下在棋盘上走格子,就这个意思。

那这题就变成一句特别朴素的话:

你从 (0,0) 到终点的步数,记为 meDist每个阻碍者从自己的位置到终点的步数,记为 ghostDist只要有一个阻碍者 ghostDist <= meDist,你就没救了。

为啥是“<=”也不行?

  • <:它能比你先到终点,在终点蹲你。
  • ==:你们能同时到终点,它正好在终点和你撞一块,你也算被抓。 只有所有阻碍者都严格比你远,你才有机会一路冲刺抢先抵达终点。

所以逻辑其实极简:

  1. 算你到终点的曼哈顿距离。
  2. 遍历每个阻碍者,看它到终点的曼哈顿距离是不是小于等于你。
  3. 如果有一个是 <=,直接返回 false;都比你远就返回 true。

别的花里胡哨的路径规划,全都不用。

三、用 Java 写出来就几行

我用地铁站举个例子,你在“0 号站”,终点是“ target 站”,一堆阻碍者从各自站点出发,大家每分钟走一站,看谁先到。

对应 Java 代码大概像这样:

publicclassEscapeGhostsSolution{

publicbooleanescapeGhosts(int[][] ghosts, int[] target){
// 你从 (0,0) 到终点的最短步数(曼哈顿距离)
int myDist = manhattan(0, 0, target[0], target[1]);

// 遍历每一个阻碍者
for (int[] g : ghosts) {
int ghostDist = manhattan(g[0], g[1], target[0], target[1]);
// 只要有一个阻碍者比你更快或同速到达终点,你就逃不掉
if (ghostDist <= myDist) {
returnfalse;
            }
        }
// 所有人都比你离终点远,你稳了
returntrue;
    }

// 曼哈顿距离小工具
privateintmanhattan(int x1, int y1, int x2, int y2){
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
    }

publicstaticvoidmain(String[] args){
        EscapeGhostsSolution s = new EscapeGhostsSolution();
int[][] ghosts = {{1, 0}, {2, 2}};
int[] target = {3, 4};
        System.out.println(s.escapeGhosts(ghosts, target)); // 随便跑个例子
    }
}

整个算法的复杂度也很轻:

  • 假设有 n 个阻碍者,
  • 就是算一次你的距离,再算 n 次阻碍者的距离,
  • 时间复杂度 O(n),空间 O(1),在面试里属于那种“看懂就结束”的题。

四、容易想错的地方

这题常见两个误区,我当时在便利店站着也在脑子里过了一遍:

  1. 误区一:要不要考虑中途拦截?很多人会想:阻碍者是不是会在半路堵我? 其实不用单独算。 因为大家速度一样,只要它比你近终点,它就可以选择一条路径,在某个时刻和你走到同一格(包括终点),这在数学上是可以证明的,你可以理解为:它完全有时间调整路线去“截胡”。

  2. 误区二:我要不要找一条“更绕但更安全”的路?对不起,没有用。 你绕路,只会让你总步数变大,meDist 变大,而阻碍者的 ghostDist 不会变大,甚至人家也可以绕一点,但总之不可能因为你绕路而“反超”一只比你更近终点的阻碍者。

所以这一题的本质,其实不是路径规划,而是:比较谁离终点更有优势。

行,我泡面也该吃完了,就先说到这。你可以自己在 IDE 里把那段 Java 代码敲一遍,多改几个 ghosts 和 target 跑跑,体会一下只看曼哈顿距离也能把这题做干净的感觉。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领,也可以链接我微信:hls404