程序员老鬼

同事被炒鱿鱼了,结果人家动作快得跟闪电似的,东西一会儿就收拾走了,工作群退,联系人一删,干净利落。。

这位同事执行力也太强了。

前脚被通知走人,后脚就开始清场,桌面一收,电脑一交,杯子、充电器、小摆件全带走,速度快得像早就演练过。工作群退得也干脆,通讯录该删删,该拉黑拉黑,一点多余情绪都不留。

Image

最搞的是中午领导还想找他问事,估计是想补两句流程,或者让人家交代点什么,结果一看,好家伙,自己也没了。消息发不出去,人也联系不上,领导这会儿脸估计都僵住了。

其实这事挺打工人的。公司裁人的时候讲效率,员工离开的时候也讲效率,大家都别演深情。你都把人清出去了,还指望人家继续待命、随叫随到,那不就是想多了嘛。

面试题:游戏中弱角色的数量

有些题一看就想两层循环:每个角色去找有没有人攻击、防御都比它高。

这个写法我第一眼就不太信。

角色数量一上来,O(n^2) 基本就是等着超时。这个题真正别扭的地方不在“比较两个属性”,而在怎么避免同攻击力的角色互相误伤。

题目说,一个角色是弱角色,必须存在另一个角色:

攻击力更高,防御力也更高。

注意,是攻击力更高,不是大于等于。

比如:

[5, 5]
[5, 9]

第二个防御高,但攻击一样,不能说明第一个弱。

这个坑不处理,答案就会偏大。

我的写法一般是先排序:

攻击力从大到小排。

攻击力一样时,防御力从小到大排。

然后从前往后扫,维护一个 maxDefense,表示前面已经见过的最大防御。

因为攻击力是降序,所以前面那些角色攻击力一定不小于当前角色。又因为同攻击力内部按防御升序排,同攻击力的前面防御只会更小,不会把当前角色误判成弱角色。

代码直接看:

import java.util.Arrays;

classSolution{
publicintnumberOfWeakCharacters(int[][] properties){
        Arrays.sort(properties, (a, b) -> {
if (a[0] != b[0]) {
return b[0] - a[0];      // 攻击力高的排前面
            }
return a[1] - b[1];          // 攻击力一样,防御低的排前面
        });

int weak = 0;
int maxDefense = 0;

for (int[] role : properties) {
int defense = role[1];

if (defense < maxDefense) {
                weak++;
            } else {
                maxDefense = defense;
            }
        }

return weak;
    }
}

这里最关键的是同攻击力的排序方向。

如果你写成攻击力降序、防御力也降序,就会出问题。

比如:

[7, 10]
[7, 3]

扫到 [7, 3] 时,前面已经有个 maxDefense = 10,代码会觉得它是弱角色。

但实际上它不是。

因为攻击力一样,不能算被压制。

所以同攻击力必须让防御小的先出现,这样同组里不会出现“前面防御比当前大”的情况。maxDefense 真正能压住当前角色的,只能来自攻击力更高的那一批。

这题还有一种写法是攻击力升序,然后倒着扫,也能做。但我不太喜欢,边界更绕一点。降序往前扫,人的脑子比较顺:前面都是更强攻击力的候选人,只要防御也压过来,当前就是弱角色。

复杂度也干净。

排序是 O(n log n),后面扫描一次是 O(n),额外空间除了排序本身,基本就是常数。

这题看着像数组题,实际考的是排序规则。两个字段一起排,最怕的就是把“同攻击力”这批数据处理错。攻击力相同的时候,不管防御差多少,都不能互相判弱。抓住这一点,代码就没什么花活了。