请记住,从你被打低绩效开始那一刻,你就已经不是团队的牛马,更不是嫡系,而是未来随时可以牺牲的耗材
有人在网上吐槽:一旦被打了低绩效,你就不再是“嫡系”,更像随时能被替换的耗材,于是劝大家别再责任心爆棚,干脆躺平摸鱼。
也有人附和,说公司既然不讲情分,个人就别硬扛。 我能理解这种寒心,但“摆烂”只能让处境更被动。更靠谱的做法是把情绪收一收,把边界立起来:把目标、产出、沟通记录留痕,争取一次明确的改进周期;同时悄悄补技能、拓人脉、准备备选机会
算法题:最大矩形
昨晚真是…我本来想早点收工的,结果产品那边丢过来一张“工位热力图”,说要算一块区域里“连续可用座位”的最大面积,问我能不能在接口里秒出结果。你们知道吧,这种需求听着像业务,其实一掰开就是算法题那味儿:最大矩形。反正我当时脑子里第一反应不是矩形,是“别又卡个 1024 之类的奇葩边界啊”…上次看抓包看吐那种阴影还在。
我就跟他们说,别把它想成“二维里找矩形”,那样你会一直想用暴力扫四个边,扫到你怀疑人生。换个角度,咱把每一行当成“地基”,往上累加高度,瞬间就变成一堆柱子,然后你只要会“柱状图最大矩形”就完事了。
举个很生活的画面哈:你每天打卡看到一排排工位,1 表示空着能坐,0 表示被占了。你从第一排往后走,每走到一排,你就更新一下“这一列连续空了多少天/多少排”。比如这一列今天也是 1,那高度就 +1;今天是 0,高度直接清零。这样每一排都会得到一个 heights 数组,它就是柱状图。然后最大矩形面积就等价于:在这个柱状图里找最大矩形。
柱状图那块我一般用单调栈,别怕,逻辑其实很像“排队领奶茶”,队里要保持从矮到高(单调递增),一旦来了个更矮的,就说明前面那些更高的“结算时刻”到了:它们的右边界确定了,可以计算面积了。
代码我就直接贴我当时写的 Python 版本吧,线上跑得挺稳,矩阵空的、全 0、全 1 也都能过:
from typing import List
deflargest_rectangle_area(heights: List[int]) -> int:
# 单调递增栈:存下标,保证对应高度递增
stack = [-1] # 哨兵,方便算宽度
best = 0
# 末尾加个 0,强制把栈里剩下的都结算掉
for i, h in enumerate(heights + [0]):
while stack[-1] != -1and heights[stack[-1]] > h:
height = heights[stack.pop()]
# 当前 i 是第一个比它矮的位置,所以右边界是 i-1
width = i - stack[-1] - 1
area = height * width
if area > best:
best = area
stack.append(i)
return best
defmaximal_rectangle(matrix: List[List[str]]) -> int:
ifnot matrix ornot matrix[0]:
return0
n = len(matrix[0])
heights = [0] * n
ans = 0
for row in matrix:
for j in range(n):
if row[j] == '1'or row[j] == 1:
heights[j] += 1
else:
heights[j] = 0
# 这一行作为“地基”的最大矩形
cur = largest_rectangle_area(heights)
if cur > ans:
ans = cur
return ans
if __name__ == "__main__":
grid = [
["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"],
]
print(maximal_rectangle(grid)) # 6
你看这里最关键的就两步:一是 heights 每行更新;二是每行调用一次柱状图最大矩形。复杂度是 O(m*n),m 行 n 列,基本就是线性扫两遍那种感觉,接口里不会炸。
然后我还顺手提醒了一句:你们前端别拿 0/1 的 int 和 '0'/'1' 的 str 混着传…我这里兼容了下,不然半夜你会看到面积一直是 0,然后你开始怀疑人生,最后发现是类型不对,气死。
对了我说到这突然想起来,我当时写完还去倒了杯水,回来一看监控上 QPS 还挺平稳…行吧先这样,我要去把那个“热力图”接口的日志再瞄两眼,别又有人把矩阵列数传成 0 说是“没座位”。哎这种事真能干出来。