如果遇到裁员,切记不要傻乎乎签字拿n加 1,和公司谈,可以拿到n加 3
这话听着爽,但真别照着无脑冲。
裁员这事,很多人一听到“N+1”就慌了,HR把纸往面前一推,脑子一热就签了。签完回家才发现,同组有人多谈了两个月,血压当场上来。
但网上说什么“死赖着不走就能N+3”,也别太当真。公司不是傻子,你手里有没有筹码,得看岗位、合同、绩效、裁员流程合不合规,还有公司急不急着把名额清掉。
能谈是真的,别秒签也是真的。至少先把补偿、离职日期、社保、公积金、年假、期权这些问清楚。该录音录音,该留邮件留邮件。别一上来就拍桌子,也别被HR两句话吓住。
打工人最怕的不是被裁,是稀里糊涂把自己卖便宜了。
hand = [1,2,3,6,2,3,4,7,8],groupSize = 3。
这牌能不能拆成顺子?
一眼看过去像是:
1 2 3
2 3 4
6 7 8
可以。
但我见过不少人写这题,第一反应是把数组排序,然后每次从里面抠一段连续的。这个写法不是不能做,就是代码会很别扭,删元素还容易把复杂度搞上去。
这种题我一般不真的“移动牌”,只记每张牌还剩几张。
比如这把牌统计后是:
1:1
2:2
3:2
4:1
6:1
7:1
8:1
关键点在最小的牌。
如果当前最小还没用完,比如 1 还剩 1 张,那它没得选,只能作为某个顺子的开头。因为没有 0、-1 能把它接进去。
所以看到 1,就必须拿走:
1 2 3
然后 2 和 3 的数量各减 1。
继续看下一个还没用完的最小牌,变成 2,那就必须拿:
2 3 4
再往后就是 6 7 8。
这个贪心很硬,不是拍脑袋。小牌如果不先处理,后面一定没人救它。
代码我会这么写:
from collections import Counter
defis_straight_hand(hand, group_size):
if len(hand) % group_size != 0:
returnFalse
left = Counter(hand)
for start in sorted(left):
need = left[start]
if need == 0:
continue
for card in range(start, start + group_size):
if left[card] < need:
returnFalse
left[card] -= need
returnTrue
这里有个地方容易写错。
不是每次只减 1,而是减 need。
比如:
hand = [1,1,2,2,3,3]
groupSize = 3
1 有两张,那就说明必须开两组:
1 2 3
1 2 3
如果你每次只减一张,代码也许能跑过一些样例,但碰到重复牌多的用例,就开始写一堆 while 补救。补救越多,越像没想清楚。
再看一个会失败的:
print(is_straight_hand([1,2,3,4,5], 4))
长度都不能被 4 整除,直接返回 False。这个判断要放最前面,别后面排了半天才发现组不起来。
再比如:
print(is_straight_hand([1,2,3,4,6,7,8,9], 4))
它能拆:
1 2 3 4
6 7 8 9
返回 True。
这题真正要抓住的是一句话:当前最小的剩余牌,只能当顺子的开头。
只要这个判断站得住,后面的代码就很短。
时间复杂度主要花在排序上,O(n log n)。计数表遍历时,每张牌最多被处理到固定长度范围里,整体不会太离谱。
别用列表反复 remove。那东西写起来像在模拟打牌,跑起来像在拖地。