放弃华为16级,进了体制内一个非常清闲的部门,早八晚五,原以为会越来越好,结果发现工作没意义,工资也不好看,后悔了
刚看到个贴子:有网友说自己放弃华为16级,去了体制内清闲部门,本以为日子会越过越舒坦,结果发现工作没意义、工资也不好看,现在反而后悔了。
在我看来,关键还是要想清楚自己要什么。有些人要稳定,有些人要成长,有些人要钱,没有哪个选择绝对好。怕就怕想着稳定又想要高薪,还希望工作有意义,这就容易失衡。
换个角度讲,体制内也不是不能发展,只是节奏慢、靠主动性,如果一味躺平,几年后自然会焦虑。
不过话说回来,工作嘛,不可能事事完美。选了哪条路,就尽量把路走通,别光盯着后悔。总的来说,找工作最重要的还是适合自己,踏实一点,路都会慢慢好起来。【备注:文末可领最新资料】
面试题:最大正方形
最大正方形这个题,大概意思就是:
给你一个只有 '0' 和 '1' 的二维数组(矩阵),'1' 表示这个格子是可以用的,'0' 表示不行。你要在里面找一块全是 1 的正方形,边长尽量大,最后返回这个正方形的面积(注意是面积,不是边长)。
比如有这么一块:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
里面最大的全 1 正方形是边长 2 的那块,所以答案是 2 * 2 = 4。
核心思路:别硬找,动规帮你算
暴力怎么干?穷举左上角、右下角,检查是不是正方形、是不是全 1……时间直接爆炸,面试官脸都黑了。
更聪明一点的办法,是给每个格子算一个东西:
以这个格子作为右下角,能形成的最大全 1 正方形,边长是多少?
我们定义一个 dp[i][j]:
表示以 (i, j)这个位置为右下角的,最大全 1 正方形的边长注意是“右下角”,这个很关键,不然状态转移不好写
那怎么推呢?
直觉:我要在
(i, j)这里形成一个更大的正方形,得看它的上边、左边、左上角这三个地方的情况如果
matrix[i][j] == '0',那这里根本没法做正方形,dp[i][j] = 0如果
matrix[i][j] == '1',那我能扩多大,取决于:上面 dp[i-1][j]能有多高左边 dp[i][j-1]能有多宽左上 dp[i-1][j-1]能有多大正方形
你可以脑补个图:如果上面有一根“1 的柱子”、左边有一条“1 的横线”,但左上角那个位置撑不起那么大正方形,你也只能乖乖听左上角的。
所以有个非常经典的状态转移公式:
如果 matrix[i][j] == '1':
dp[i][j] = min(
dp[i-1][j], 上边
dp[i][j-1], 左边
dp[i-1][j-1] 左上
) + 1
否则:
dp[i][j] = 0
为什么要取三个里的最小值? 你可以理解成:
三个人一起抬一个正方形,谁最弱,就按谁的极限来。
然后我们在遍历整个矩阵的过程中,顺便维护一个 max_side,记录所有 dp[i][j] 里的最大值,最后返回 max_side * max_side 就行了。
边界怎么办?
第一行、第一列,没“左边”“上边”“左上角”可以看了
但这些位置,如果自己是
'1',那它能形成的最大正方形边长只能是 1所以实现上可以:
直接让 i、j从 0 开始当 i == 0或j == 0时,如果是'1',就把dp[i][j] = 1
先来一个看着最清晰、最好懂的二维 dp 写法:
from typing import List
classSolution:
defmaximalSquare(self, matrix: List[List[str]]) -> int:
ifnot matrix ornot matrix[0]:
return0
rows, cols = len(matrix), len(matrix[0])
# 多加一行一列 0,可以少写一点边界判断
dp = [[0] * (cols + 1) for _ in range(rows + 1)]
max_side = 0
# 注意这里 i, j 从 1 开始,对应原矩阵的 i-1, j-1
for i in range(1, rows + 1):
for j in range(1, cols + 1):
if matrix[i - 1][j - 1] == '1':
dp[i][j] = min(
dp[i - 1][j], # 上
dp[i][j - 1], # 左
dp[i - 1][j - 1] # 左上
) + 1
max_side = max(max_side, dp[i][j])
# 是 '0' 的话 dp[i][j] 默认就是 0,不用管
return max_side * max_side
简单捋一下:
时间复杂度: O(m * n),m行n列,每个格子就看一眼空间复杂度: O(m * n),用了一个同尺寸的 dp 矩阵(加了一行一列,不过量级一样)
这个代码在面试里已经完全够用了,可读性很好。
如果你想装一装“空间优化”,也可以把 dp 从二维压成一维。 观察转移式:
dp[i][j] 来自:
上: dp[i-1][j]
左: dp[i][j-1]
左上: dp[i-1][j-1]
如果我们一行一行扫,其实:
dp[j]可以表示“当前行的第 j 列,对应的 dp 值”那“上边”的值就是更新之前的 dp[j]“左边”就是 dp[j-1]“左上”我们就用一个变量 prev暂存每次更新前的dp[j]
写出来大概是这样:
from typing import List
classSolution:
defmaximalSquare(self, matrix: List[List[str]]) -> int:
ifnot matrix ornot matrix[0]:
return0
rows, cols = len(matrix), len(matrix[0])
dp = [0] * (cols + 1)
max_side = 0
for i in range(1, rows + 1):
prev = 0# 对应左上角 dp[i-1][j-1]
for j in range(1, cols + 1):
temp = dp[j] # 还没更新前的 dp[j] = 上边
if matrix[i - 1][j - 1] == '1':
dp[j] = min(dp[j], dp[j - 1], prev) + 1
max_side = max(max_side, dp[j])
else:
dp[j] = 0
prev = temp # 下一轮用作左上角
return max_side * max_side
这个版本:
时间还是 O(m * n)但空间变成了 O(n),只用了一行 dp 数组+几个变量
如果你在面试里能先写出二维版,讲清楚含义,再说一句“其实可以空间压缩成一维,思路是这样的……”,基本上这一题就拿满分了。
差不多就这样,一个“最大正方形”就吃透了。你要是愿意,可以顺手把“最大矩形”、“全 1 矩形”那俩题一起刷了,思路串一串会更爽。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB