程序员老鬼

同事发了18万年终奖,领导只收到6万,以为是发错了,去找总监核实,结果总监说:你作为领导,绩效不理想。但你下属绩效好,这很正常。

有网友说,公司发年终奖,他同事到手18万,领导自己才6万。领导一看人都懵了,第一反应不是反思,而是觉得财务是不是发错了,赶紧跑去找总监核实。

结果总监一句话直接把场面干安静了:你是领导没错,但你绩效不理想。你下属绩效好,奖金高,很正常。

Image

这事最扎心的点就在这儿。很多人当了领导之后,总觉得自己天然就该比下面人拿得多,毕竟职位高嘛。可公司真按结果分钱的时候,脸就有点挂不住了。

下属干得好,拿18万;领导带队没带出成绩,拿6万。听着刺耳,但逻辑还真没啥毛病。

估计领导去问之前,还想着能查出个系统bug。没想到最后查出来,bug是自己。HR看完都得低头喝口水。

面试题:一手顺子

牌都摊开了,最小那张还没被用掉,你却想从中间开始凑顺子,这种写法我第一眼就不太信。

“一手顺子”这个题,坑不在代码长,坑在顺序。给你一堆牌 hand,每组必须是 groupSize 张连续牌,问能不能刚好分完。

比如:

hand = [1,2,3,6,2,3,4,7,8]
groupSize = 3

可以拆成:

[1,2,3]
[2,3,4]
[6,7,8]

但如果最小的牌是 1,那它没得选。它只能作为某一组的开头,必须去找 2、3、...。你让它去当后面的牌,不现实,因为没有更小的牌在前面补。

所以这题我一般不搞花活,就盯着最小牌处理。

先把每张牌出现次数统计起来,还要能按牌面从小到大拿,Java 里用 TreeMap 正合适。

代码可以这么写:

import java.util.Map;
import java.util.TreeMap;

classSolution{
publicbooleanisNStraightHand(int[] hand, int groupSize){
if (hand == null || hand.length == 0) {
returnfalse;
        }

if (hand.length % groupSize != 0) {
returnfalse;
        }

        TreeMap<Integer, Integer> cardBox = new TreeMap<>();

for (int card : hand) {
            cardBox.put(card, cardBox.getOrDefault(card, 0) + 1);
        }

while (!cardBox.isEmpty()) {
int start = cardBox.firstKey();

for (int card = start; card < start + groupSize; card++) {
                Integer left = cardBox.get(card);

if (left == null) {
returnfalse;
                }

if (left == 1) {
                    cardBox.remove(card);
                } else {
                    cardBox.put(card, left - 1);
                }
            }
        }

returntrue;
    }
}

这里有个细节,别小看这句:

int start = cardBox.firstKey();

每次都从当前最小的牌开拆。

比如当前最小是 5,那它必须拉着 6、7、8... 组成一组。要是 6 不在,直接失败。因为这张 5 已经没有别的地方能去了。

有些写法会先排序数组,再用 HashMap 扣次数,也能做。但我不太喜欢那种写法,循环里会反复扫已经没用的牌,代码看着也容易绕。TreeMap 的好处是:谁还没用完,谁就在表里;谁用完了,直接删掉。现场排问题时,这种结构更顺眼。

再看一个容易误判的例子:

hand = [1,2,3,4,5]
groupSize = 4

长度 5 不能被 4 整除,别往后算了,直接 false。这个判断要放前面,不然就是白跑。

还有这种:

hand = [1,2,3,4,6,7,8,9]
groupSize = 4

第一组可以是 [1,2,3,4],剩下 [6,7,8,9],也可以。

如果是:

hand = [1,2,3,4,6,7,8,10]
groupSize = 4

第一组扣完后,最小是 6,需要 6、7、8、9,结果 9 没有,失败。别被后面的 10 晃了眼,它补不了 9 的坑。

这题的判断顺序就一句话:最小的牌先安排,安排不了就别挣扎。复杂度主要在 TreeMap 的增删查上,大概是 O(n log n),够用了。 算法题有时候不是看你能不能写得高级,是看你有没有抓住那个“最没退路”的元素。最小牌,就是这题里最没退路的那张。