LeetCode 题解工作台

用邮票贴满网格图

给你一个 m x n 的二进制矩阵 grid ,每个格子要么为 0 (空)要么为 1 (被占据)。 给你邮票的尺寸为 stampHeight x stampWidth 。我们想将邮票贴进二进制矩阵中,且满足以下 限制 和 要求 : 覆盖所有 空 格子。 不覆盖任何 被占据 的格子。 我们可以放入任意…

category

4

题型

code_blocks

8

代码语言

hub

3

相关题

当前训练重点

困难 · 贪心·invariant

bolt

答案摘要

根据题目描述,每一个空格子都必须被邮票覆盖,而且不能覆盖任何被占据的格子。因此,我们可以遍历二维矩阵,对于每个格子,如果以该格子为左上角的 $stampHeight \times stampWidth$ 的区域内的所有格子都是空格子(即没有被占据),那么我们就可以在该格子处放置一个邮票。 为了快速判断一个区域内的所有格子是否都是空格子,我们可以使用二维前缀和。我们用 表示二维矩阵中从 到 的…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 贪心·invariant 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个 m x n 的二进制矩阵 grid ,每个格子要么为 0 (空)要么为 1 (被占据)。

给你邮票的尺寸为 stampHeight x stampWidth 。我们想将邮票贴进二进制矩阵中,且满足以下 限制 和 要求 :

  1. 覆盖所有  格子。
  2. 不覆盖任何 被占据 的格子。
  3. 我们可以放入任意数目的邮票。
  4. 邮票可以相互有 重叠 部分。
  5. 邮票不允许 旋转 。
  6. 邮票必须完全在矩阵  。

如果在满足上述要求的前提下,可以放入邮票,请返回 true ,否则返回 false 。

 

示例 1:

输入:grid = [[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0]], stampHeight = 4, stampWidth = 3
输出:true
解释:我们放入两个有重叠部分的邮票(图中标号为 1 和 2),它们能覆盖所有与空格子。

示例 2:

输入:grid = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]], stampHeight = 2, stampWidth = 2 
输出:false 
解释:没办法放入邮票覆盖所有的空格子,且邮票不超出网格图以外。

 

提示:

  • m == grid.length
  • n == grid[r].length
  • 1 <= m, n <= 105
  • 1 <= m * n <= 2 * 105
  • grid[r][c] 要么是 0 ,要么是 1
  • 1 <= stampHeight, stampWidth <= 105
lightbulb

解题思路

方法一:二维前缀和 + 二维差分

根据题目描述,每一个空格子都必须被邮票覆盖,而且不能覆盖任何被占据的格子。因此,我们可以遍历二维矩阵,对于每个格子,如果以该格子为左上角的 stampHeight×stampWidthstampHeight \times stampWidth 的区域内的所有格子都是空格子(即没有被占据),那么我们就可以在该格子处放置一个邮票。

为了快速判断一个区域内的所有格子是否都是空格子,我们可以使用二维前缀和。我们用 si,js_{i,j} 表示二维矩阵中从 (1,1)(1,1)(i,j)(i,j) 的子矩阵中被占据的格子的数量。即 si,j=si1,j+si,j1si1,j1+gridi1,j1s_{i, j} = s_{i - 1, j} + s_{i, j - 1} - s_{i - 1, j - 1} + grid_{i-1, j-1}

那么以 (i,j)(i, j) 为左上角,且高度和宽度分别为 stampHeightstampHeightstampWidthstampWidth 的子矩阵的右下角坐标为 (x,y)=(i+stampHeight1,j+stampWidth1)(x, y) = (i + stampHeight - 1, j + stampWidth - 1),我们可以通过 sx,ysx,j1si1,y+si1,j1s_{x, y} - s_{x, j - 1} - s_{i - 1, y} + s_{i - 1, j - 1} 来计算出该子矩阵中被占据的格子的数量。如果该子矩阵中被占据的格子的数量为 00,那么我们就可以在 (i,j)(i, j) 处放置一个邮票,放置邮票后,这 stampHeight×stampWidthstampHeight \times stampWidth 的区域内的所有格子都会变成被占据的格子,我们可以用二维差分数组 dd 来记录这一变化。即:

di,jdi,j+1di,y+1di,y+11dx+1,jdx+1,j1dx+1,y+1dx+1,y+1+1\begin{aligned} d_{i, j} &\leftarrow d_{i, j} + 1 \\ d_{i, y + 1} &\leftarrow d_{i, y + 1} - 1 \\ d_{x + 1, j} &\leftarrow d_{x + 1, j} - 1 \\ d_{x + 1, y + 1} &\leftarrow d_{x + 1, y + 1} + 1 \end{aligned}

最后,我们对二维差分数组 dd 进行前缀和运算,可以得出每个格子被邮票覆盖的次数。如果某个格子没有被占据,且被邮票覆盖的次数为 00,那么我们就无法将邮票放置在该格子处,因此我们需要返回 false\texttt{false}。如果所有“没被占据的格子”都成功被邮票覆盖,返回 true\texttt{true}

时间复杂度 O(m×n)O(m \times n),空间复杂度 O(m×n)O(m \times n)。其中 mmnn 分别是二维矩阵的高度和宽度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def possibleToStamp(
        self, grid: List[List[int]], stampHeight: int, stampWidth: int
    ) -> bool:
        m, n = len(grid), len(grid[0])
        s = [[0] * (n + 1) for _ in range(m + 1)]
        for i, row in enumerate(grid, 1):
            for j, v in enumerate(row, 1):
                s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + v
        d = [[0] * (n + 2) for _ in range(m + 2)]
        for i in range(1, m - stampHeight + 2):
            for j in range(1, n - stampWidth + 2):
                x, y = i + stampHeight - 1, j + stampWidth - 1
                if s[x][y] - s[x][j - 1] - s[i - 1][y] + s[i - 1][j - 1] == 0:
                    d[i][j] += 1
                    d[i][y + 1] -= 1
                    d[x + 1][j] -= 1
                    d[x + 1][y + 1] += 1
        for i, row in enumerate(grid, 1):
            for j, v in enumerate(row, 1):
                d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1]
                if v == 0 and d[i][j] == 0:
                    return False
        return True
speed

复杂度分析

指标
时间complexity is O(m _n) for building prefix sums and iterating possible stamp placements. Space complexity is O(m_ n) for the prefix sum matrix and auxiliary coverage arrays.
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Checks if you can combine greedy choices with fast submatrix checks using prefix sums.

  • question_mark

    Wants you to avoid O(m _n_ stampHeight*stampWidth) naive checks for stamp placement.

  • question_mark

    Seeks a method to validate coverage efficiently after greedy placement.

warning

常见陷阱

外企场景
  • error

    Attempting to check each stamp position by iterating over all cells inside the stamp, leading to timeouts.

  • error

    Overlapping stamps incorrectly without verifying that all empty cells are eventually covered.

  • error

    Ignoring boundary conditions where stamp placement would exceed grid dimensions.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Change the grid to allow rectangular stamps of varying dimensions and compute coverage feasibility.

  • arrow_right_alt

    Introduce obstacles that cannot be stamped and check if complete coverage of remaining empty cells is possible.

  • arrow_right_alt

    Count the minimum number of stamps required to cover all empty cells using a similar greedy plus validation approach.

help

常见问题

外企场景

用邮票贴满网格图题解:贪心·invariant | LeetCode #2132 困难