题目
在一个 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:
输入: n = 5, mines = [[4, 2]]
输出: 2
解释: 在上面的网格中,最大加号标志的阶只能是2。一个标志已在图中标出。
示例 2:
输入: n = 1, mines = [[0, 0]]
输出: 0
解释: 没有加号标志,返回 0 。
提示:
1 <= n <= 500
1 <= mines.length <= 5000
0 <= xi, yi < n
每一对 (xi, yi) 都 不重复
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/largest-plus-sign
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
暴力破解
- 超时
- 解题思路
遍历所有点,取所有点的长度,取最大长度
public static int orderOfLargestPlusSign0(int n, int[][] mines) {
HashSet<Point> mineSet= new HashSet<>();
for (int i = 0; i < mines.length; i++) {
Point point =new Point();
point.x=mines[i][0];
point.y=mines[i][1];
mineSet.add(point);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Point center= new Point();
center.x=i;
center.y=j;
if(mineSet.contains(center))
{
System.out.print(0+"\t");
}
else
{
System.out.print(1+"\t");
}
}
System.out.println();
}
int maxLen=0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Point center= new Point();
center.x=i;
center.y=j;
if(mineSet.contains(center))
{
continue;
}
List<Point> allPoint = getAllPoint(n, center,mineSet);
int len = allPoint.size()/4+1;
maxLen=Math.max(len,maxLen);
}
}
return maxLen;
}
public static List<Point> getAllPoint(int n,Point center,HashSet<Point> mineSet)
{
List<Point> rs = new ArrayList<>();
rs.add(center);
int up = center.x-1;
int right = center.y+1;
int down = center.x+1;
int left =center.y-1;
while (up>=0 && right<n&& down<n && left>=0) {
Point upPoint= new Point();
upPoint.x=up;
upPoint.y=center.y;
Point rightPoint= new Point();
rightPoint.x=center.x;
rightPoint.y=right;
Point downPoint= new Point();
downPoint.x=down;
downPoint.y=center.y;
Point leftPoint= new Point();
leftPoint.x=center.x;
leftPoint.y=left;
if(mineSet.contains(upPoint) ||
mineSet.contains(rightPoint) ||
mineSet.contains(downPoint) ||
mineSet.contains(leftPoint))
{
break;
}
rs.add(upPoint);
rs.add(rightPoint);
rs.add(downPoint);
rs.add(leftPoint);
up--;
right++;
down++;
left--;
}
return rs;
}
public static class Point
{
public Integer x;
public Integer y;
@Override
public boolean equals(Object obj) {
return (this.x==((Point) obj).x) && (this.y==((Point) obj).y);
}
@Override
public int hashCode() {
return x.hashCode()+y.hashCode();
}
}
优化枚举
- 可以通过
- 解题思路
设置一个map,将排除点标记为1,然后枚举所有点的长度,取最大长度,将上一个方法的哈希和实体转为简单的数组了。可以通过了
public static int orderOfLargestPlusSign(int n, int[][] mines) {
//初始化map值为0的矩阵
int[][] map= new int[n][n];
//
for (int i = 0; i < mines.length; i++) {
map[mines[i][0]][mines[i][1]]=1;
}
int maxLen=0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if(map[i][j]==1)
{
continue;
}
int len = getLen(n,i,j,map);
maxLen=Math.max(len,maxLen);
}
}
return maxLen;
}
public static int getLen(int n,int x,int y,int[][] map)
{
int up = x-1;
int right = y+1;
int down = x+1;
int left =y-1;
int len=1;
while (up>=0 && right<n&& down<n && left>=0) {
if (map[up][y] == 1 ||
map[x][right] == 1 ||
map[down][y] == 1 ||
map[x][left] == 1) {
break;
}
up--;
right++;
down++;
left--;
len++;
}
return len;
}
动态规划
- 解题思路
每个点所能形成的大加好标志。可以理解为四个方向连续的1的个数。并且是四个方法连续1个数的最小值。所以可以设置dp[][],为每个点为最大连续个数,然后取四个方向的最小值。以下代码还可以优化简写,但简写了之后,不太好理解,为了保证可读性,所以就没有在简写了。
public static int orderOfLargestPlusSign3(int n, int[][] mines) {
int[][] dp = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
dp[i][j]=n;
}
}
for (int i = 0; i < mines.length; i++) {
dp[mines[i][0]][mines[i][1]]=0;
}
for (int i = 0; i < n; i++) {
int left=0;
for (int j = 0; j < n; j++) {
left = dp[i][j]>0?left+1:0;
dp[i][j]=Math.min(dp[i][j],left);
}
}
for (int i = 0; i < n; i++) {
int right=0;
for (int j = n-1; j>=0; j--) {
right = dp[i][j]>0?right+1:0;
dp[i][j]=Math.min(dp[i][j],right);
}
}
for (int i = 0; i < n; i++) {
int up = 0;//循环up,x轴
for (int j = 0; j < n; j++) {
up = dp[j][i] > 0 ? up + 1 : 0;
dp[j][i] = Math.min(dp[j][i], up);
}
}
for (int i = 0; i < n; i++) {
int down = 0;
for (int j = n - 1; j >= 0; j--) {
down = dp[j][i] > 0 ? down + 1 : 0;
dp[j][i] = Math.min(dp[j][i], down);
}
}
int rs = 0;
for (int[] e : dp) {
rs = Math.max(rs, Arrays.stream(e).max().getAsInt());
}
return rs;
}
标签:标志,center,Point,int,mines,++,加号,dp,最大
From: https://www.cnblogs.com/huacha/p/16875642.html