某大厂员工:领导让他报裁员名单,结果这哥们竟然把自己写上去,拿着20多万的赔偿,去付买房的首付!
刚看到个贴子,说某大厂员工被要求上报裁员名单,结果他脑袋一热,把自己名字写上去,还顺手拿了二十多万赔偿去交房子首付。
我觉得这事吧,网友虽然笑成一片,但不少人其实是羡慕的。说到底,这哥们敢这么干,是因为算清了账:赔偿到位、后路稳妥、需求明确。不是冲动,是“性价比”算明白了。
换个角度想,有些人天天在岗位上内耗,既不满意现状,又不敢动弹,最后卡在中间最难受。反倒是这位兄弟,像下棋一样,果断把子落下去了。
总的来说嘛,职场路上没有标准解法,但能为自己的选择负责,就是成年人最大的底气。【备注:文末可领最新资料】
面试题:员工奖金
说个很现实的事儿哈,年末一到,群里最热的话题基本就俩:一个是去哪儿团建,另一个就是——奖金怎么发。 很多公司都是“排排坐,评分在这儿,奖金你自己算算看”,听着简单,其实背后有个挺经典的算法题。
员工排成一排,怎么发最省钱?
假设现在有一排员工,每个人都有一个绩效分数,用一个数组表示,比如:
ratings = [1, 2, 2]
规则是这样的:
每个人至少要拿 1 份奖金(不可能有人是 0,对吧,脸上挂不住)。 如果一个员工的绩效分比相邻同事高,那他拿的奖金也必须比对方多(不然肯定有人拍桌子)。
目标:在满足上面两个条件的前提下,让公司发出去的总奖金尽可能少,最后算出每个人该发几份。
听着是不是有点像“分糖果”?本质就是一个问题,只不过这里我们叫“奖金”,看起来高级一点。
先说一个“看起来对,其实不对”的想法
很多同学第一反应都是: “那我就从左往右扫一遍,谁比左边分数高,我就给他比左边多 1 份,其他人就发 1 呗。”
比如 ratings = [1, 2, 3]:
第一个人:奖金 1 第二个人:分数高于左边,奖金 2 第三个人:再高,奖金 3 → 完美
但问题来了,换个例子:ratings = [3, 2, 1]:
第一个人:奖金 1(先随便给个 1) 第二个:分数比左边低,那就还是 1? 第三个:也比左边低,还是 1?
最后变成 [1, 1, 1],明显不符合“分数高的人奖金要多”这条规则。 所以只从左往右看是不够的,右边的同事也会“抗议”的。
正解思路:两边都得看,左右各来一遍
比较靠谱的做法是这么玩儿:
先从左往右扫一遍,只管“比左边的人高怎么办”; 再从右往左扫一遍,只管“比右边的人高怎么办”; 最后对每个人取“两个方向里需要的最大奖金数”。
举个稍微复杂点的例子: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