技术总监拿了45万年终突然离职,我们以为是被别人挖走了,结果是总监发现自己管理的两个核心项目,被公司偷偷转移给新空降的领导~
刚看到个贴子,说一技术总监拿了45万年终奖转头就提离职,本来同事都以为是被大厂高薪挖走,结果内幕是:他辛苦几年打下来的两个核心项目,被公司悄悄转给了新空降的领导。
网友回帖有说“拿了钱就别矫情的”,也有替总监抱不平的,觉得这是赤裸裸架空。
我觉得这事吧,核心不是钱,而是“被消失的控制权”。项目被拿走,就像房本上把你名字擦掉,再厚的年终奖也只是分手费。对公司来说,这是短期算计,把人当一次性工具;对个人来说,就是个信号:这里已经不值得继续押注。
算法题:缺失的区间
你有一段连续的整数区间 [lower, upper], 然后手里又有一个已经排好序、互不重复的数组 nums,里面的数字都在这段区间里。
但是呢,这个数组不一定把区间里的所有数字都覆盖了,中间可能断断续续少一截一截的。 题目的意思就是:把这些“缺失的连续区间”找出来。
举个很具体的例子:
lower = 0
upper = 9
nums = [0, 1, 3, 7, 8]
那整段区间是 0,1,2,3,4,5,6,7,8,9, 你手里的只有 0,1,3,7,8,所以少了:
24,5,69
常见的输出格式会长这样:
["2", "4->6", "9"]
单个数字直接写数字,多于一个数字就写成 start->end 这种形式。
题目就这个意思,没别的花活。
我一般会先在脑子里画个数轴,大概是这样:
lower ... 若干数字 ... upper
我们要找的,其实就是:“数组中的相邻数字”之间差出来的那一段。
但这里有两个“隐形邻居”很关键:
lower的前一个数:lower - 1upper的后一个数:upper + 1
为什么要整这俩?
因为你得把“开头缺一段”和“结尾缺一段”也统一成“中间缺一段”的写法,不然逻辑会变得很乱。
所以完整的套路是:
设一个变量
prev = lower - 1,表示“上一个出现的数字”把数组
nums后面强行拼一个upper + 1,当成“终点哨兵”然后从左到右遍历
nums + [upper + 1],记当前数字为cur每次看
cur - prev的差:
起点就是 prev + 1终点就是 cur - 1如果起点==终点,缺的是一个数 不相等就是一段区间
如果差小于 2,说明中间没少数字,直接往后走
如果差大于等于 2,说明中间至少缺了一个数
每轮结束记得 prev = cur
核心其实就一句话:
所有的“缺口”都存在于“两个相邻已知数字之间”。
from typing import List
deffind_missing_ranges(nums: List[int], lower: int, upper: int) -> List[str]:
res = []
# 1. 上一个看过的数字,从 lower - 1 开始,方便统一处理
prev = lower - 1
# 2. 在末尾拼一个 upper + 1,当成终点哨兵
# 这样结尾缺的那段也能在循环里一次性处理掉
for cur in nums + [upper + 1]:
# 如果中间至少差了 2,说明有东西缺了
if cur - prev >= 2:
start = prev + 1
end = cur - 1
if start == end:
# 只缺一个数
res.append(str(start))
else:
# 缺一整段
res.append(f"{start}->{end}")
# 别忘了更新 prev
prev = cur
return res
这个函数就是标准解了,丢到 LeetCode 那种地方也能跑。
我们用几个例子捋一捋
1)数组是空的
print(find_missing_ranges([], 1, 5)) # ['1->5']
解释:啥都没有,那整个 [1,5] 都是缺的。
2)中间有洞
print(find_missing_ranges([1, 3, 7], 0, 9))
# ['0', '2', '4->6', '8->9']
prev = -1,cur = 1→ 缺0prev = 1,cur = 3→ 缺2prev = 3,cur = 7→ 缺4->6prev = 7,cur = 10(哨兵) → 缺8->9
你会发现头尾完全是被“当成中间情况”处理掉的,这就是那个 lower - 1 和 upper + 1 的意义。
3)完全不缺
print(find_missing_ranges([1, 2, 3], 1, 3)) # []
每次 cur - prev 都小于 2,自然啥都不加。
复杂度顺手算一下
其实也简单:
只遍历了一遍 nums,额外就一个哨兵,所以时间复杂度是O(n)存结果的数组,最极端也就是 “数字/区间互相交替”,数量也是 O(n),所以空间复杂度也是O(n)
对面试官说的时候,别说得太花,就一句:“单次线性扫描,时间 O(n),额外空间 O(n) 存答案。” 就够了。
几个特别容易写挂的地方我再捋一遍:
nums可能是空的,要特判或者让算法自己兜住(上面这版是能兜住的)可能
nums[0]比lower大,别漏了开头那段可能
nums[-1]比upper小,别漏了结尾那段输出格式一定要区分:
一个数: "2"多个数: "2->5"
搞定这些,其实这题就属于那种:只要你敢写完,调两下就能 AC 的题。
行,我就说到这儿,你可以自己把代码粘进本地跑几组数据试试,有啥想扩展的版本(比如允许重复、没排好序那种),也可以再一起改一版“加强版”的。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB