暑期实习打卡 Day1

85 阅读1分钟

算法 1

最大正方形

在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积

思路

经典动态规划

    public int maximalSquare(char[][] grid) {
        int n = grid.length;
        int m = grid[0].length;

        int[][] dp = new int[n+1][m+1];
        int ans = 0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(grid[i-1][j-1]=='1'){
                    int t = Math.min(dp[i-1][j],dp[i][j-1]);
                    t = Math.min(t, dp[i-1][j-1]);
                    dp[i][j] = t+1;
                }
                else{
                    dp[i][j] = 0;
                }
                ans = Math.max(dp[i][j], ans);
            }
        }
        return ans * ans;
    }

最大以1为边界的正方形

给你一个由若干 0 和 1 组成的二维网格 grid,请你找出边界全部由 1 组成的最大 正方形 子网格,并返回该子网格中的元素数量。如果不存在,则返回 0

思路

这题不能用DP解决,因为无法抽象出子问题 所以我们通过前缀和简化问题

    public int largest1BorderedSquare(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int[][] rs = new int[m][n + 1], cs = new int[n][m + 1];
        for (int i = 0; i < m; ++i)
            for (int j = 0; j < n; ++j) {
                rs[i][j + 1] = rs[i][j] + grid[i][j]; // 每行的前缀和
                cs[j][i + 1] = cs[j][i] + grid[i][j]; // 每列的前缀和
            }
        for (int d = Math.min(m, n); d > 0; --d) // 从大到小枚举正方形边长 d
            for (int i = 0; i <= m - d; ++i)
                for (int j = 0; j <= n - d; ++j) // 枚举正方形左上角坐标 (i,j)
                    if (rs[i][j + d] - rs[i][j] == d && // 上边
                        cs[j][i + d] - cs[j][i] == d && // 左边 
                        rs[i + d - 1][j + d] - rs[i + d - 1][j] == d && // 下边
                        cs[j + d - 1][i + d] - cs[j + d - 1][i] == d)   // 右边
                        return d * d;
        return 0;
    }