心动厂员工爆料,加班后在工位很晕,天旋地转,出公司差点摔倒,回家一量血压高达150!
刚看到个贴子,说字节有同学加班后当场天旋地转,出门差点摔倒,回家一量血压150,真挺吓人的。加班嘛大家都经历过,但能把人逼到这种程度,就不是“忙一点”的问题了,是身体在发警报了。
我看网友回帖,有说大厂强度正常的,也有嘲讽“早就习惯了”的。怎么说呢,这种正常化高强度,其实最可怕。就像天天坐地铁挤成沙丁鱼,挤久了你会觉得理所当然,但身体不会帮你装糊涂。
从我的角度看,问题的关键不是加不加班,而是有没有底线、有没有换命式的消耗。血压150可不是小事,那已经是身体在拉闸断电了。工作再重要,也不值当把自己卷进医院。
不过话说回来,不是让大家躺平,但节奏真得自己把握。命是自己的,老板不会替你住院。【备注:文末可领最新资料】
面试题:杀掉进程
这个“杀掉进程”的题,说白了就是模拟系统里“结束任务”。 给你三样东西:
一个 pid数组:所有正在跑的进程 ID一个 ppid数组:每个进程的父进程 ID(下标一一对应)一个 kill:你要干掉的那个进程 ID
要求:把这个进程以及它所有子孙进程的 ID 都找出来,返回成一个列表。
你可以脑补成: 任务管理器里你结束了一个“主程序”,它下面一串子进程也会一起被干掉。
把进程关系想成一棵树
只要看到 “父进程 / 子进程”“要一起删除下面所有的”,其实已经在疯狂暗示:
这玩意儿就是一棵树,从
ppid -> pid的那种“父指向子”的树。
举个小例子:
pid = [1, 3, 10, 5]
ppid = [0, 1, 3, 3]
kill = 3
对应关系:
1 的父进程是 0(可以理解为系统) 3 的父进程是 1 10 的父进程是 3 5 的父进程是 3
画成树差不多就是:
0
└── 1
└── 3
├── 10
└── 5
如果要 kill = 3,那被杀掉的进程就是:[3, 10, 5],自己 + 所有后代。
所以核心问题就变成了:
给你一棵“用数组隐式存”的树,给一个结点,找出它整棵子树的所有结点。
解题思路:先建表,再遍历
思路很自然,两步走:
把父子关系整理一下用一个字典:
parent -> [children...]
遍历 pid和ppid对于每一对 (p, pp),把p挂到children[pp]下面
从要杀的进程开始,往下把所有子孙都走一遍这个就随便了:
用 DFS(深度优先) 可以 用 BFS(广度优先,队列) 也可以
走到的每一个结点,都放进答案里,最后返回就行。
来一段比较接地气的写法,变量名也别太抽象:
from collections import defaultdict, deque
defkillProcess(pid, ppid, kill):
# 1. 建 parent -> children 的映射
children = defaultdict(list)
for child, parent in zip(pid, ppid):
children[parent].append(child)
# 2. 从 kill 这个点开始 BFS
res = []
q = deque([kill])
while q:
cur = q.popleft()
res.append(cur)
# 把当前结点的所有子进程扔进队列
for c in children.get(cur, []):
q.append(c)
return res
用刚才那个例子测一下:
pid = [1, 3, 10, 5]
ppid = [0, 1, 3, 3]
kill = 3
print(killProcess(pid, ppid, kill)) # 可能输出 [3, 10, 5] 或 [3, 5, 10],顺序无所谓
5. 换成 DFS 也行(递归版本)
如果你更喜欢递归,也可以这么写:
from collections import defaultdict
defkillProcess(pid, ppid, kill):
children = defaultdict(list)
for child, parent in zip(pid, ppid):
children[parent].append(child)
res = []
defdfs(x):
res.append(x)
for c in children.get(x, []):
dfs(c)
dfs(kill)
return res
这个版本的逻辑是:
先把当前进程放进结果 再递归把所有子进程都走一遍
6. 复杂度
整体很朴素:
建 children映射要扫一遍数组,O(n)遍历树的时候,每个结点最多进一次队列 / 调一次递归,也是 O(n) 所以总时间复杂度: O(n)额外空间:字典 + 队列 / 递归栈,都是 O(n)级别
几个顺手可以注意的小点:
如果 kill恰好是“根进程”,那结果就是所有进程全被干掉如果数据量特别大,又用的是递归 DFS,可能会有栈深度问题, 这种时候就更推荐上面那个 队列 BFS 的写法 返回顺序题目一般不要求,只要包含的元素对就行
这个题本质就是:
“用
ppid建一棵树,然后从要删的结点出发,把整棵子树的点都收集起来”。
思路很直白,实现也不绕弯,面试里属于那种一眼就要想到“树 + 遍历”的题。 你要是能把这个套路记住,碰到类似“删某个结点及所有后代”的题,基本就是同一套写法直接抄过来就能用。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB