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
posted on 2021-05-11 21:27  雾恋过往  阅读(53)  评论(0编辑  收藏  举报

Live2D