同事被炒鱿鱼了,结果人家动作快得跟闪电似的,东西一会儿就收拾走了,工作群退,联系人一删,干净利落
真给我看乐了。
同事上午刚被通知不用来了,结果人家一点没拖泥带水。电脑关了,杯子拿走,抽屉清空,工作群退掉,微信该删的删,一套动作下来比公司走流程还快。
最搞笑的是中午领导还想找他问点事,翻半天发现人没了,聊天框也没了,自己还躺在删除名单里。那一刻领导估计也懵:不是,我还没发完最后一波指令呢?
但说真的,这事还挺打工人的。平时公司讲效率,裁人的时候也挺效率,那人家离场效率高一点,也没啥毛病。都被炒了,还指望人家继续在线待命,随叫随到,顺便保持体面?
成年人职场就是这样,关系到点就断。别谈什么情怀,工资结清,东西带走,江湖不见。
四层 for 一写出来,这题基本就没味了。
不是不能过,n 小的时候确实能混过去。但面试或者刷题时,我一般不太信这种写法。因为题目叫“统计特殊四元组”,真正要看的不是你会不会枚举,而是你能不能把等式拆开。
题目要求找这样的下标:
i < j < k < l
nums[i] + nums[j] + nums[k] == nums[l]
第一眼看,四个下标都要管,很烦。
但这个式子稍微挪一下:
nums[i] + nums[j] == nums[l] - nums[k]
这地方就能下手了。
左边是前面的两个数之和,右边是后面的两个数之差。只要保证下标顺序没乱,统计次数就行。
最笨的写法大概是这样:
defcount_quadruplets(nums):
n = len(nums)
ans = 0
for i in range(n):
for j in range(i + 1, n):
for k in range(j + 1, n):
for l in range(k + 1, n):
if nums[i] + nums[j] + nums[k] == nums[l]:
ans += 1
return ans
这段代码没毛病,就是太直。四层循环一套,时间复杂度 O(n^4)。数据一大就开始难看。
我更愿意从右往左扫 j。
为什么扫 j?
因为一旦固定了 j,左边只需要枚举 i < j,右边的 k、l 可以提前放到哈希表里。
哈希表里存什么?
存:
nums[l] - nums[k]
也就是右边能凑出来的差值出现了几次。
代码可以这样写:
from collections import defaultdict
defcount_quadruplets(nums):
n = len(nums)
right_diff = defaultdict(int)
total = 0
# j 至少从 n - 3 开始,后面要留 k 和 l
for j in range(n - 3, 0, -1):
k = j + 1
# 把当前 k 和它后面的 l 组成差值,丢进右侧统计表
for l in range(k + 1, n):
right_diff[nums[l] - nums[k]] += 1
# 再枚举左边的 i,看 nums[i] + nums[j] 有没有出现过
for i in range(j):
need = nums[i] + nums[j]
total += right_diff[need]
return total
这段代码最容易看错的地方在这里:
k = j + 1
每次 j 往左挪一格,就把新的 k 加进右侧哈希表。
这样哈希表里维护的永远是:
j < k < l
左边枚举的是:
i < j
两边一合,顺序自然就是:
i < j < k < l
不需要额外判断下标。
拿个数组过一下:
nums = [1, 2, 3, 6]
当 j = 1 时,左边有 i = 0,右边有 k = 2, l = 3。
右边差值是:
6 - 3 = 3
左边和值是:
1 + 2 = 3
对上了,答案加 1。
这题如果只写暴力,像是在验题;用哈希拆等式,才像是在解题。
复杂度从 O(n^4) 压到 O(n^2),空间复杂度是 O(n^2) 级别,存的是右侧差值次数。实际代码不长,关键是别把哈希表维护早了或者晚了,下标顺序一乱,答案就会多算。