我烟草,我老婆电网,一年加起来大概50个,看病啥的基本不花钱~
烟草配电网,这组合一摆出来,味儿就出来了。
一个在烟草,一个在电网,七七八八再加点外头的小投资,一年50个左右。看病基本不花钱,假期还稳,隔三差五能出去玩。你别说,这种日子放网上,真挺容易把一群打工人看沉默的。
底下有人说,这不就是普通双职工天花板,稳定、体面、抗风险。也有人阴阳一句,说现在还敢这么晒,多少有点不拿网友当外人。两边其实都没说错。
我看这种帖子,第一反应不是羡慕,是“命题已经做完了”。选对单位,真能少挨好多社会的打。普通人看完除了点个酸赞,也只能回头继续改PPT,顺手把年假申请先关掉。
算法题:粉碎糖果
一上来就模拟,十有八九会把自己写晕。
“粉碎糖果”这题,表面看像二维数组遍历,真写起来最容易错的地方不是怎么找相同糖果,而是粉碎之后还要下落,下落完可能继续粉碎。这就不是扫一遍能收工的题,它本质上是个“反复处理直到稳定”的过程。这个味道,跟线上排查有点像:你以为改完一层就结束了,结果下面那层状态又变了。
这题我一般不先想花活,先拆成两步:
先标记这一轮哪些糖果该碎。 再让每一列往下掉。 如果这一轮一个都没碎,说明盘面稳定,直接返回。
关键点在“标记”不能直接改值。因为你一边扫一边改,后面判断就脏了。比较稳的写法,是把要碎的格子先改成负数,等这一轮扫描完,再统一处理。
Python 代码我会这么写,够短,也够现场:
from typing import List
defcandy_crush(board: List[List[int]]) -> List[List[int]]:
rows, cols = len(board), len(board[0])
whileTrue:
changed = False
# 1. 横向标记
for i in range(rows):
for j in range(cols - 2):
v = abs(board[i][j])
if v != 0and v == abs(board[i][j + 1]) == abs(board[i][j + 2]):
board[i][j] = -v
board[i][j + 1] = -v
board[i][j + 2] = -v
changed = True
# 2. 纵向标记
for i in range(rows - 2):
for j in range(cols):
v = abs(board[i][j])
if v != 0and v == abs(board[i + 1][j]) == abs(board[i + 2][j]):
board[i][j] = -v
board[i + 1][j] = -v
board[i + 2][j] = -v
changed = True
ifnot changed:
return board
# 3. 下落
for j in range(cols):
write = rows - 1
for i in range(rows - 1, -1, -1):
if board[i][j] > 0:
board[write][j] = board[i][j]
write -= 1
while write >= 0:
board[write][j] = 0
write -= 1
这段代码有两个地方比较值钱。
一个是 abs()。因为我们用负数做“待粉碎标记”,如果这里不取绝对值,横着扫完再竖着扫,判断就乱了。
另一个是“下落”别真的一格一格模拟交换。那种写法又慢又丑,还容易把边界写炸。直接每列搞个 write 指针,从下往上收集正数,再把上面的空位补 0,干净很多。
比如这一列原来是:
[1, -2, 3, -4, 5]
处理完应该变成:
[0, 0, 1, 3, 5]
负数和 0 都别要,只把还活着的正数往下压。
这题难的不是算法有多高级,而是你得接受它就是个“循环直到稳定”的模型。很多人第一次写,会执着于“一次遍历解决全部问题”,这地方我第一眼就不太信。能连锁反应的题,通常就别想着一轮结束。
写这种题,脑子里最好一直盯着两个状态:这一轮谁该消失,消失完盘面怎么重排。别混着写,混着写后面基本都得返工。