764. 最大加号标志

在一个 ​​n x n​​ 的矩阵 ​​grid​​ 中,除了在数组 ​​mines​​ 中给出的元素为 ​​0​​,其他每个元素都为 ​​1​​。​​mines[i] = [xi, yi]​​表示 ​​grid[xi][yi] == 0​

返回  ​grid​ 中包含 ​​1​​ 的最大的 轴对齐 加号标志的阶数 。如果未找到加号标志,则返回 ​​0​​ 。

一个 ​​k​​ 阶由 ​​1​​ 组成的 “轴对称”加号标志 具有中心网格 ​​grid[r][c] == 1​​ ,以及4个从中心向上、向下、向左、向右延伸,长度为 ​​k-1​​,由 ​​1​​ 组成的臂。注意,只有加号标志的所有网格要求为 ​​1​​ ,别的网格可能为 ​​0​​ 也可能为 ​​1​​ 。

 示例 1:

[leetcode每日一题]11.9_dp

例 2:

[leetcode每日一题]11.9_dp_02

输入: n = 1, mines = [[0, 0]]
输出: 0
解释: 没有加号标志,返回 0 。

 提示:

  • ​1 <= n <= 500​
  • ​1 <= mines.length <= 5000​
  • ​0 <= xi, yi < n​
  • 每一对 ​​(xi, yi)​​ 都 不重复

Solution

暴力。对每一个点上下左右搜索连续1的个数,四个方向的最小值作为该点的加号臂长。由于n的范围很小,所以能够支持O(n^3)的做法。

代码(C++)

class Solution {
private:
int arr[500][500] = {0}; // 为了方便,0表示1,1表示0
public:
int orderOfLargestPlusSign(int n, vector<vector<int>>& mines) {
for(auto&& mine : mines){
arr[mine[0]][mine[1]] = 1;
}
int cur_max = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(arr[i][j])continue;
int c1=0, c2=0, c3=0, c4=0;
int a=i;
while(a>=0&&!arr[a][j]){
a--;
c1++;
}
if(c1<=cur_max)continue;
a=i;
while(a<n&&!arr[a][j]){
a++;
c2++;
}
if(c2<=cur_max)continue;
int b=j;
while(b>=0&&!arr[i][b]){
b--;
c3++;
}
if(c3<=cur_max)continue;
b=j;
while(b<n&&!arr[i][b]){
b++;
c4++;
}
if(c4<=cur_max)continue;
int c = min(min(c1, c2), min(c3, c4));
cur_max = c;
}
}
return cur_max;
}
};

当然题解的用空间换时间的做法也很好,因为一个点的状态可以由旁边的点的状态得知,因此使用dp记录下四个方向的臂长,之后利用两点之间的相关性横向遍历一次,纵向遍历一次,找出最大臂长即可。

注意遍历的方向。

[leetcode每日一题]11.9_dp_03

代码(Python)

class Solution:
def orderOfLargestPlusSign(self, n: int, mines: List[List[int]]) -> int:
dp = [[n] * n for _ in range(n)]
banned = set(map(tuple, mines))
for i in range(n):
# left
count = 0
for j in range(n):
count = 0 if (i, j) in banned else count + 1
dp[i][j] = min(dp[i][j], count)
# right
count = 0
for j in range(n - 1, -1, -1):
count = 0 if (i, j) in banned else count + 1
dp[i][j] = min(dp[i][j], count)
for j in range(n):
# up
count = 0
for i in range(n):
count = 0 if (i, j) in banned else count + 1
dp[i][j] = min(dp[i][j], count)
# down
count = 0
for i in range(n - 1, -1, -1):
count = 0 if (i, j) in banned else count + 1
dp[i][j] = min(dp[i][j], count)
return max(map(max, dp))

作者:力扣官方题解
链接:https://leetcode.cn/problems/largest-plus-sign/solutions/1956480/zui-da-jia-hao-biao-zhi-by-leetcode-solu-jirt/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。