Python技术迷

某大厂员工:领导让他报裁员名单,结果这哥们竟然把自己写上去,拿着20多万的赔偿,去付买房的首付!

刚看到个贴子,说某大厂员工被要求上报裁员名单,结果他脑袋一热,把自己名字写上去,还顺手拿了二十多万赔偿去交房子首付。

Image

我觉得这事吧,网友虽然笑成一片,但不少人其实是羡慕的。说到底,这哥们敢这么干,是因为算清了账:赔偿到位、后路稳妥、需求明确。不是冲动,是“性价比”算明白了。

换个角度想,有些人天天在岗位上内耗,既不满意现状,又不敢动弹,最后卡在中间最难受。反倒是这位兄弟,像下棋一样,果断把子落下去了。

总的来说嘛,职场路上没有标准解法,但能为自己的选择负责,就是成年人最大的底气。【备注:文末可领最新资料】

面试题:员工奖金

说个很现实的事儿哈,年末一到,群里最热的话题基本就俩:一个是去哪儿团建,另一个就是——奖金怎么发。 很多公司都是“排排坐,评分在这儿,奖金你自己算算看”,听着简单,其实背后有个挺经典的算法题。

员工排成一排,怎么发最省钱?

假设现在有一排员工,每个人都有一个绩效分数,用一个数组表示,比如:

ratings = [1, 2, 2]

规则是这样的:

  1. 每个人至少要拿 1 份奖金(不可能有人是 0,对吧,脸上挂不住)。
  2. 如果一个员工的绩效分比相邻同事高,那他拿的奖金也必须比对方多(不然肯定有人拍桌子)。

目标:在满足上面两个条件的前提下,让公司发出去的总奖金尽可能少,最后算出每个人该发几份。

听着是不是有点像“分糖果”?本质就是一个问题,只不过这里我们叫“奖金”,看起来高级一点。

先说一个“看起来对,其实不对”的想法

很多同学第一反应都是: “那我就从左往右扫一遍,谁比左边分数高,我就给他比左边多 1 份,其他人就发 1 呗。”

比如 ratings = [1, 2, 3]:

  • 第一个人:奖金 1
  • 第二个人:分数高于左边,奖金 2
  • 第三个人:再高,奖金 3 → 完美

但问题来了,换个例子:ratings = [3, 2, 1]:

  • 第一个人:奖金 1(先随便给个 1)
  • 第二个:分数比左边低,那就还是 1?
  • 第三个:也比左边低,还是 1?

最后变成 [1, 1, 1],明显不符合“分数高的人奖金要多”这条规则。 所以只从左往右看是不够的,右边的同事也会“抗议”的。

正解思路:两边都得看,左右各来一遍

比较靠谱的做法是这么玩儿:

  1. 先从左往右扫一遍,只管“比左边的人高怎么办”;
  2. 再从右往左扫一遍,只管“比右边的人高怎么办”;
  3. 最后对每个人取“两个方向里需要的最大奖金数”。

举个稍微复杂点的例子:ratings = [1, 3, 2, 2, 1]

第一遍:从左往右

规则:如果 ratings[i] > ratings[i-1],那 bonus[i] = bonus[i-1] + 1,否则就是 1。

  • 初始:bonus = [1, 1, 1, 1, 1]
  • i=1:3 > 1 → bonus[1] = 2 → [1, 2, 1, 1, 1]
  • i=2:2 < 3 → 还是 1 → [1, 2, 1, 1, 1]
  • i=3:2 == 2 → 还是 1 → [1, 2, 1, 1, 1]
  • i=4:1 < 2 → 还是 1 → [1, 2, 1, 1, 1]

只看左边的时候,结果是 [1, 2, 1, 1, 1]。

第二遍:从右往左

这次我们重新搞一个数组,从右往左扫: 规则:如果 ratings[i] > ratings[i+1],那 right_bonus[i] = right_bonus[i+1] + 1,否则 1。

  • 初始:right = [1, 1, 1, 1, 1]
  • i=3:2 > 1 → right[3] = 2 → [1, 1, 1, 2, 1]
  • i=2:2 == 2 → 还是 1 → [1, 1, 1, 2, 1]
  • i=1:3 > 2 → right[1] = 2 + 1 = 3 → [1, 3, 1, 2, 1]
  • i=0:1 < 3 → 还是 1 → [1, 3, 1, 2, 1]

右边视角下是 [1, 3, 1, 2, 1]。

最后合并一下

对每个员工,既要满足左边的要求,也要满足右边的要求,所以取两边里较大的那一个:

  • index 0:max(1, 1) = 1
  • index 1:max(2, 3) = 3
  • index 2:max(1, 1) = 1
  • index 3:max(1, 2) = 2
  • index 4:max(1, 1) = 1

最终奖金是 [1, 3, 1, 2, 1],总和是 8,在满足规则的前提下已经是最省钱的方案了。

时间复杂度:两遍循环,O(n); 空间复杂度:两个数组,也是 O(n),面试的时候这么说就行。

用 Python 写一下,逻辑其实挺顺

直接上代码,你一看就懂那种:

from typing import List

defcalc_bonus(ratings: List[int]) -> List[int]:
    n = len(ratings)
if n == 0:
return []

# 从左往右
    left = [1] * n
for i in range(1, n):
if ratings[i] > ratings[i - 1]:
            left[i] = left[i - 1] + 1

# 从右往左
    right = [1] * n
for i in range(n - 2, -1, -1):
if ratings[i] > ratings[i + 1]:
            right[i] = right[i + 1] + 1

# 取两个方向的最大值,就是每个人最终的奖金份数
    bonus = [max(left[i], right[i]) for i in range(n)]
return bonus

if __name__ == "__main__":
    ratings_list = [1, 3, 2, 2, 1]
    bonus_list = calc_bonus(ratings_list)
    print("绩效:", ratings_list)
    print("奖金份数:", bonus_list)
    print("总奖金份数:", sum(bonus_list))

你拿这个函数,随便给一组评分进去,立刻就能算出“在不闹矛盾的前提下,公司最少得发多少份奖金”。

如果哪天你领导真跟你说:“来,你帮我设计个公平又省钱的奖金规则”, 你就可以一脸淡定:“早写好算法了,给我一组绩效分我就能算。”

-END-

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

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB