Python技术迷

北京一大厂员工被裁,拿到了56万赔偿。其媳妇太兴奋,在某平台发图分享喜悦,结果截图里公司名称没打码。

刚刷到这个,真给我看愣了。

北京某大厂员工被裁,拿了56万赔偿,本来这事到这儿也算体面退场。结果他媳妇太高兴,直接把赔偿截图发网上了,关键公司名字还没打码。

Image

等反应过来删帖,已经晚了,截图到处传。公司、部门、姓名,全被同事给扒出来了。

56万还没捂热乎,先喜提全公司围观。大哥估计人都麻了,自己被裁没崩,回家一看网上全是自己……

今日算法题

数组里一个数重复了,一个数消失了:Python 解「错误的集合」

数组是 [1, 2, 2, 4],长度为 4,按规矩里面应该放着 1、2、3、4。

结果 2 出现了两次,3 直接没了。

这题叫“错误的集合”,要求返回:

[重复的数字, 缺失的数字]

题目本身不绕,真正容易写乱的是:一边找重复值,一边又想算缺失值,最后循环里塞了一堆判断。我的习惯是把两件事拆开。先把出现过的数字记下来,重复值自然会撞出来;再从 1 扫到 n,谁没出现,谁就是缺失值。

代码不用写得太花:

from typing import List


classSolution:
deffindErrorNums(self, nums: List[int]) -> List[int]:
        appeared = [False] * (len(nums) + 1)
        repeated = -1

for value in nums:
if appeared[value]:
                repeated = value
continue

            appeared[value] = True

        missing = -1

for value in range(1, len(nums) + 1):
ifnot appeared[value]:
                missing = value
break

return [repeated, missing]

拿 [1, 2, 2, 4] 跑一遍。

第一次遇到 2,把 appeared[2] 标记成 True。第二次再遇到 2,对应位置已经被标记过,重复数字就是它。

接着检查 1 到 4:

1:出现过
2:出现过
3:没有出现
4:出现过

所以最终返回:

[2, 3]

这里数组长度要开成 n + 1,因为数字范围是 1 到 n,下标 0 根本不用。这个地方少开一位,碰到数字 n 就会直接越界,属于很低级但很常见的错误。

再补一个边界数据:

nums = [2, 2]

长度为 2,完整集合应该是 [1, 2]。现在 2 重复,1 缺失,结果就是:

[2, 1]

这套写法的时间复杂度是 O(n)。前面遍历一次数组,后面再扫描一次数字范围,没有嵌套循环。空间复杂度也是 O(n),额外用了一个布尔数组。

有人会直接写:

for value in range(1, len(nums) + 1):
if value notin nums:
        ...

这段看着短,我一般不会这么交。value not in nums 每次都要重新扫描数组,外层再跑 n 次,整体会退化成 O(n²)。数据小的时候看不出区别,数据一大,耗时就不太好看了。

算法题里,代码短不是目的。循环里有没有偷偷重复扫描数据,这个才值得盯一下。