764. 最大加号标志
题目:
在一个大小在 (0, 0) 到 (N-1, N-1) 的2D网格 grid 中,除了在 mines 中给出的单元为 0,其他每个单元都是 1。网格中包含 1 的最大的轴对齐加号标志是多少阶?返回加号标志的阶数。如果未找到加号标志,则返回 0。
一个 k" 阶由 1 组成的“轴对称”加号标志具有中心网格 grid[x][y] = 1 ,以及4个从中心向上、向下、向左、向右延伸,长度为 k-1,由 1 组成的臂。下面给出 k" 阶“轴对称”加号标志的示例。注意,只有加号标志的所有网格要求为 1,别的网格可能为 0 也可能为 1。
k 阶轴对称加号标志示例:
阶 1:
0 0 0
0 1 0
0 0 0阶 2:
0 0 0 0 0
0 0 1 0 0
0 1 1 1 0
0 0 1 0 0
0 0 0 0 0阶 3:
0 0 0 0 0 0 0
0 0 0 1 0 0 0
0 0 0 1 0 0 0
0 1 1 1 1 1 0
0 0 0 1 0 0 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0
示例 1:
输入: N = 5, mines = [[4, 2]]
输出: 2
解释:11111
11111
11111
11111
11011在上面的网格中,最大加号标志的阶只能是2。一个标志已在图中标出。
示例 2:
输入: N = 2, mines = []
输出: 1
解释:11
11没有 2 阶加号标志,有 1 阶加号标志。
示例 3:
输入: N = 1, mines = [[0, 0]]
输出: 0
解释:0
没有加号标志,返回 0 。
思路:
对于每个中心点坐标 (r, c),从四个方向计算从 (r, c) 开始最长连续 1 的个数。用动态规划的方法来看,如果 grid[r][c] 是 0,那么臂长就是 0,如果 grid[r][c] 是 l, 那么臂长就是当前方向上连续 1 的个数再加 1。
举个例子,假设当前方向为左,网格中有一行为 01110110, 那么对应的连续 1 的个数就是 012301201。可以观察到,每个数要么是它相邻左边的数加 1, 要么是 0。
对于每个中心点,让 dp[r][c] 为四个方向中最小的连续 1 的个数。显然,dp 数组中最大的值就是我们要的结果。
Python版
class Solution(object):
def orderOfLargestPlusSign(self, N, mines):
banned = {tuple(mine) for mine in mines}
dp = [[0] * N for _ in range(N)]
ans = 0
for r in range(N): #固定行
count = 0
for c in range(N): #列从0到N是从左到右遍历,dp[r][c]代表的就是这个位置可以向左扩展多少个格子
count = 0 if (r,c) in banned else count+1 #判断出grid[r][c]可以向左扩几个格子
dp[r][c] = count
count = 0
for c in range(N-1, -1, -1): #列从0到N是从右到左遍历,dp[r][c]代表的就是这个位置可以向右扩展多少个格子
count = 0 if (r,c) in banned else count+1 #判断出grid[r][c]可以向右扩几个格子
if count < dp[r][c]: dp[r][c] = count #从向左和向右中取小的
for c in range(N): #固定列
count = 0
for r in range(N): #行从0到N是从上到下遍历,dp[r][c]代表的就是这个位置可以向上扩展多少个格子
count = 0 if (r,c) in banned else count+1 #判断出grid[r][c]可以向上扩几个格子
if count < dp[r][c]: dp[r][c] = count #dp[r][c]已经是从向左和向右中取小的了,在和向上的比,取小的
count = 0
for r in range(N-1, -1, -1): #行从0到N是从下到上遍历,dp[r][c]代表的就是这个位置可以向下扩展多少个格子
count = 0 if (r, c) in banned else count+1 #判断出grid[r][c]可以向下扩几个格子
if count < dp[r][c]: dp[r][c] = count #dp[r][c]已经是从向左、向右、向上中小的了,在和向下的比,还取小的,此时dp[r][c]就是代表这个点的阶数了
if dp[r][c] > ans: ans = dp[r][c] #取最大阶数的,当然这个步骤也可以在dp数组计算完后来取的
return ans