背绩效了,HRBP在场,Leader主动说出:“工作那么多年,累了,想歇歇,希望你能为我争取个大礼包”。这是什么意思?
背绩效背到一半,Leader当着HRBP的面来一句:“干这么多年,累了,想歇歇,帮我争取个大礼包。”这话一出来,空气都得静三秒。
这不就是职场黑话现场教学吗。表面像在感慨人生,实际是在递话:我不想硬扛了,但也不想自己开口裸辞,看看公司愿不愿意按“体面点”的方式送我走。HRBP在场更关键,这种话不是随便感叹,是说给该听的人听的。
有人说,Leader八成是闻到味儿了,知道自己位置不稳,先把台阶摆出来。你别说,这种老江湖发言还真挺典,话说得软,意思一点不软。
背绩效的人在旁边估计都听懵了。本来以为是复盘,结果听成了离职谈判预告。成年人上班,有时候真不是谁能力不行,是谁先把话说到那个份上。HR听完,估计已经开始在心里算包了。
面试题:Nim 游戏
一上来就写递归,十有八九会把 Nim 游戏 写复杂了。
这题其实没那么多花活。面试官真想看的,也不是你会不会模拟拿石子,而是你能不能第一眼看出来:这个题根本不用搜状态,直接看 n 和 4 的关系就够了。
题目规则很短:一堆石子,两个人轮流拿,每次只能拿 1 到 3 个,谁拿到最后一颗谁赢。假设双方都足够聪明,问先手会不会赢。
我一般看到这种“轮流操作、双方最优”的题,先不急着写代码,先找最小样本。
n = 1,先手直接拿完,赢。n = 2,先手也赢。n = 3,先手还是赢。n = 4,这时候味道就不对了。 你先手拿 1,后手拿 3。 你拿 2,后手拿 2。 你拿 3,后手拿 1。 反正先手必输。
到这里基本就该警觉了:4 是个分界点。
再往后看:
n = 5,先手拿 1,给对方留 4,赢。n = 6,先手拿 2,给对方留 4,赢。n = 7,先手拿 3,给对方留 4,赢。n = 8,不管怎么拿,都会给对方留 5、6、7,这几个都是能赢的位置,所以自己输。
规律已经很明显了:只要是 4 的倍数,先手必输;不是 4 的倍数,先手必赢。
这地方别背,真要理解一下。
因为每一轮两个人总共最多会拿走 4 个石子。你只要能把局面控制成“留给对手 4 的倍数”,对面其实就很难翻。对手拿 1 个,你就拿 3 个;对手拿 2 个,你就拿 2 个;对手拿 3 个,你就拿 1 个。始终把总数重新凑回 4 的倍数,最后那个吃亏的人就是对面。
所以这题的 Java 写法,短到有点不像算法题:
publicclassSolution{
publicbooleancanWinNim(int n){
return n % 4 != 0;
}
}
就这一行判断,够了。
有些人写这题,喜欢上来就 dp[i],也不是不行,但这题真没必要。你真要把思路摊开写,动态规划大概是这样:
publicclassSolution{
publicbooleancanWinNim(int n){
if (n <= 3) {
returntrue;
}
boolean[] dp = newboolean[n + 1];
dp[1] = true;
dp[2] = true;
dp[3] = true;
dp[4] = false;
for (int i = 5; i <= n; i++) {
dp[i] = !dp[i - 1] || !dp[i - 2] || !dp[i - 3];
}
return dp[n];
}
}
这个状态转移也不难理解:当前玩家只要能走到一个“对手必输”的状态,自己就赢。所以只要 i-1、i-2、i-3 里有一个是 false,那 dp[i] 就是 true。
但问题也正好在这。你都已经把表推出来了,很快就会发现:
dp[4] = falsedp[8] = falsedp[12] = false
规律直接跳脸。那还保留数组干什么,纯属多绕一圈。
这题真正值钱的点,不在代码量,在于你有没有把“最优策略 + 规律归纳”这层看出来。很多博文喜欢把它包装成博弈论,好像很玄。其实落地一点,就是一句话:
先手想赢,就努力把石子数留成 4 的倍数给对方。
面试里这种题,经常不是考你会不会写,而是考你会不会收。该用公式的时候别硬上递归,该一行结束的时候别拖成半页。