0
点赞
收藏
分享

微信扫一扫

leetcode2132. 用邮票贴满网格图(hard)(69双周赛)

WikongGuan 2022-01-12 阅读 60

用邮票贴满网格图


力扣链接

解题思路

大佬题解
解题前提: 需要知道二维前缀和与二维差分

  • 二维前缀和 + 二维差分

代码

class Solution {
    public boolean possibleToStamp(int[][] grid, int h, int w) {
        int m = grid.length;
        int n = grid[0].length;

        //二维前缀和
        int[][] sum = new int[m + 1][n + 1];
        //二维差分
        int[][] diff = new int[m + 1][n + 1];

        //遍历求前缀和
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                //二维前缀和计算公式
                sum[i][j] = sum[i - 1][j] + sum[i][j - 1] + grid[i - 1][j - 1] - sum[i - 1][j - 1];
            }
        }

        //对所有能容纳邮票大小的空格进行范围+1操作
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                //从左上角坐标为0中寻找能容纳邮票的二维区域
                if (grid[i][j] == 0) {
                    
                    int x = i + h;
                    int y = j + w;
                    //如果x,y在边界内,且由左上角[i,j]和右下角[x - 1, y - 1]围成的区域和为0,则说明该区域可以放置邮票,进行区域+1操作
                    if (x <= m && y <= n && (sum[x][y] + sum[i][j] - sum[i][y] - sum[x][j] == 0)) {
                        ++diff[i][j];
                        ++diff[x][y];
                        --diff[i][y];
                        --diff[x][j];
                    }
                }
            }
        }

        //还原二维差分矩阵对应的计数矩阵,这里用滚动数组实现
        int[] pre = new int[n + 1];
        int[] cur = new int[n + 1];
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                cur[j + 1] = diff[i][j] + cur[j] + pre[j + 1] - pre[j];
                //如果某一个格的数组原值为0,差分数组的前缀和也为0,则说明该格未被邮票覆盖,返回false
                if (cur[j + 1] == 0 && grid[i][j] == 0) {
                    return false;
                }
            }
            int[] tmp = cur;
            cur = pre;
            pre = tmp;
        }

        return true;
    }
}

复杂度

  • 时间复杂度: O(mn)
  • 空间复杂度: O(mn)
举报

相关推荐

0 条评论