最大加号标志

题目

在一个 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;
    }
posted @ 2022-11-09 23:52  花茶冰糖  阅读(45)  评论(0编辑  收藏  举报