Python技术迷

还没面试,国企HR把我删了??

这网友投了个国企,面试还没影呢,HR先加微信,问得那叫一个细。本硕哪儿读的,籍贯哪儿,家里啥情况,感觉不像招人,像查户口。

问完一句“OK同学,等通知”,人就消失了。等了两周,一点动静没有,网友想着问问进度吧,结果消息一发:被对方拒收。

好家伙,面都没见上,先被删了。

Image

最扎心的是后面才听说,人家岗位可能早就内定好了,加你微信就是补个流程,材料凑一凑,样子做一做,最后统一清场。

这就很离谱了。你说不合适就不合适,发个模板拒信也行啊,直接删人是什么操作?打工人还在那儿认真准备,HR那边已经开始打扫战场了。

合着不是候选人,是流程里的背景板。HR删得挺快,尊重倒是一点没加载出来。

算法题:柠檬水找零

第一位顾客掏 10 块,你手里一张 5 块都没有,收银台当场就炸。

这就是「柠檬水找零」这题最容易被写复杂的地方。它不是让你算有多少种找零方案,也不是让你回溯所有可能。每杯柠檬水 5 块,顾客只会给 5、10、20。你手里能不能一路找下去,只看两张钞票的库存:5 块和 10 块。

我写这题时,一般不会上来就建什么零钱数组。因为 20 块不用存,收到 20 只是收入,不参与后面找零。真正有用的只有 5 和 10。

现场逻辑是这样:

收到 5 块,直接收下。

收到 10 块,必须找 5 块。没有 5 块,失败。

收到 20 块,要找 15 块。这里我会优先用一张 10 加一张 5,而不是三张 5。

为什么?

因为 5 块太关键了。后面不管遇到 10 还是 20,都离不开 5。你为了找一个 20,把三张 5 全掏出去,后面来个 10 就直接死。

代码可以写得很短:

deflemonade_change(bills):
    five = 0
    ten = 0

for idx, pay in enumerate(bills):
if pay == 5:
            five += 1

elif pay == 10:
if five == 0:
returnFalse
            five -= 1
            ten += 1

else:  # pay == 20
if ten > 0and five > 0:
                ten -= 1
                five -= 1
elif five >= 3:
                five -= 3
else:
returnFalse

returnTrue

拿一组数据走一下:

orders = [5, 5, 5, 10, 20]
print(lemonade_change(orders))

这组能过。

过程大概是这样:

前面三个 5 收进来,手里有 3 张 5。 第 4 个顾客给 10,找出去 1 张 5,手里剩 2 张 5,多了 1 张 10。 第 5 个顾客给 20,优先用 10 + 5 找零,刚好。

再看一个容易翻车的:

orders = [5, 5, 10, 10, 20]
print(lemonade_change(orders))

这个返回 False。

很多人第一眼觉得前面收了不少钱,应该够找。这个判断不对。收银台不是看总金额,是看面额结构。

走到最后一个 20 时,手里有两张 10,但是只有 0 张 5。要找 15,必须带一张 5,不然两张 10 加起来是 20,没法硬找。

这题的坑就在这里:钱够,不代表能找开。

如果想看得更清楚,可以加一个排查版,把失败位置打出来:

defcheck_counter(bills):
    box = {5: 0, 10: 0}

for i, pay in enumerate(bills):
if pay == 5:
            box[5] += 1
elif pay == 10:
if box[5] < 1:
                print("failed at", i, "pay=10", box)
returnFalse
            box[5] -= 1
            box[10] += 1
else:
if box[10] >= 1and box[5] >= 1:
                box[10] -= 1
                box[5] -= 1
elif box[5] >= 3:
                box[5] -= 3
else:
                print("failed at", i, "pay=20", box)
returnFalse

returnTrue

算法复杂度没什么花活。

每个顾客只处理一次,时间复杂度是 O(n)。只用了两个计数变量,空间复杂度是 O(1)。

这题真正要记住的不是代码,而是那个取舍:找 20 的时候,能用 10 + 5 就别用 5 + 5 + 5。后面还要不要活,就看你手里留没留 5 块。