Skip to content

Commit 207d9d3

Browse files
committed
feat: add solutions to lc problem: No.2132
No.2132.Stamping the Grid
1 parent 9818d4b commit 207d9d3

File tree

8 files changed

+495
-409
lines changed

8 files changed

+495
-409
lines changed

solution/2100-2199/2132.Stamping the Grid/README.md

Lines changed: 165 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,24 @@
6060

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

63-
根据题给的约束,很容易推出,一个格子能贴邮票的条件为,在加上邮票的长和宽后,右下角不越界的情况下,当前子区域中所有格子的和为 0
63+
根据题目描述,每一个空格子都必须被邮票覆盖,而且不能覆盖任何被占据的格子。因此,我们可以遍历二维矩阵,对于每个格子,如果以该格子为左上角的 $stampHeight \times stampWidth$ 的区域内的所有格子都是空格子(即没有被占据),那么我们就可以在该格子处放置一个邮票
6464

65-
那么显然我们可以维护一个二维的前缀和数组,在 `O(1)` 的时间复杂度下就可以判断每次遍历到的格子是否能贴邮票
65+
为了快速判断一个区域内的所有格子是否都是空格子,我们可以使用二维前缀和。我们用 $s_{i,j}$ 表示二维矩阵中从 $(1,1)$ 到 $(i,j)$ 的子矩阵中被占据的格子的数量。即 $s_{i, j} = s_{i - 1, j} + s_{i, j - 1} - s_{i - 1, j - 1} + grid_{i-1, j-1}$
6666

67-
而因为贴邮票的操作,可以概括为将当前子区域的所有格子的值都置为 `1`,很自然的就能想到用一个二维的差分数组来维护贴邮票后的状态。
67+
那么以 $(i, j)$ 为左上角,且高度和宽度分别为 $stampHeight$ 和 $stampWidth$ 的子矩阵的右下角坐标为 $(x, y) = (i + stampHeight - 1, j + stampWidth - 1)$,我们可以通过 $s_{x, y} - s_{x, j - 1} - s_{i - 1, y} + s_{i - 1, j - 1}$ 来计算出该子矩阵中被占据的格子的数量。如果该子矩阵中被占据的格子的数量为 $0$,那么我们就可以在 $(i, j)$ 处放置一个邮票,放置邮票后,这 $stampHeight \times stampWidth$ 的区域内的所有格子都会变成被占据的格子,我们可以用二维差分数组 $d$ 来记录这一变化。即:
6868

69-
最后只要对该差分数组再求一次二维前缀和,只要当前格子的和为 `0`,就意味着存在没有覆盖完全的情况,直接返回 `false` 即可。
69+
$$
70+
\begin{aligned}
71+
d_{i, j} &\leftarrow d_{i, j} + 1 \\
72+
d_{i, y + 1} &\leftarrow d_{i, y + 1} - 1 \\
73+
d_{x + 1, j} &\leftarrow d_{x + 1, j} - 1 \\
74+
d_{x + 1, y + 1} &\leftarrow d_{x + 1, y + 1} + 1
75+
\end{aligned}
76+
$$
7077

71-
需要注意的是二维数组的下标关系,具体参考如下
78+
最后,我们对二维差分数组 $d$ 进行前缀和运算,可以得出每个格子被邮票覆盖的次数。如果某个格子没有被占据,且被邮票覆盖的次数为 $0$,那么我们就无法将邮票放置在该格子处,因此我们需要返回 $\texttt{false}$。如果所有“没被占据的格子”都成功被邮票覆盖,返回 $\texttt{true}$
7279

73-
`s[i + 1][j + 1]` 表示第 i 行第 j 列左上部分所有元素之和,其中 i, j 下标从 0 开始。
74-
75-
`s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + nums[i][j]`
76-
77-
以 (x1, y1) 为左上角,(x2, y2) 为右下角的子矩阵和 `sub = s[x2 + 1][y2 + 1] - s[x2 + 1][y1] - s[x1][y2 + 1] + s[x1][y1]`
80+
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是二维矩阵的高度和宽度。
7881

7982
<!-- tabs:start -->
8083

@@ -89,26 +92,22 @@ class Solution:
8992
) -> bool:
9093
m, n = len(grid), len(grid[0])
9194
s = [[0] * (n + 1) for _ in range(m + 1)]
92-
for i, row in enumerate(grid):
93-
for j, v in enumerate(row):
94-
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + v
95-
96-
d = [[0] * (n + 1) for _ in range(m + 1)]
97-
for i, row in enumerate(grid):
98-
for j, v in enumerate(row):
99-
if v == 0:
100-
x, y = i + stampHeight, j + stampWidth
101-
if x <= m and y <= n and s[x][y] - s[x][j] - s[i][y] + s[i][j] == 0:
102-
d[i][j] += 1
103-
d[i][y] -= 1
104-
d[x][j] -= 1
105-
d[x][y] += 1
106-
107-
cnt = [[0] * (n + 1) for _ in range(m + 1)]
108-
for i, row in enumerate(grid):
109-
for j, v in enumerate(row):
110-
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j]
111-
if v == 0 and cnt[i + 1][j + 1] == 0:
95+
for i, row in enumerate(grid, 1):
96+
for j, v in enumerate(row, 1):
97+
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + v
98+
d = [[0] * (n + 2) for _ in range(m + 2)]
99+
for i in range(1, m - stampHeight + 2):
100+
for j in range(1, n - stampWidth + 2):
101+
x, y = i + stampHeight - 1, j + stampWidth - 1
102+
if s[x][y] - s[x][j - 1] - s[i - 1][y] + s[i - 1][j - 1] == 0:
103+
d[i][j] += 1
104+
d[i][y + 1] -= 1
105+
d[x + 1][j] -= 1
106+
d[x + 1][y + 1] += 1
107+
for i, row in enumerate(grid, 1):
108+
for j, v in enumerate(row, 1):
109+
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1]
110+
if v == 0 and d[i][j] == 0:
112111
return False
113112
return True
114113
```
@@ -122,30 +121,27 @@ class Solution {
122121
public boolean possibleToStamp(int[][] grid, int stampHeight, int stampWidth) {
123122
int m = grid.length, n = grid[0].length;
124123
int[][] s = new int[m + 1][n + 1];
125-
for (int i = 0; i < m; ++i) {
126-
for (int j = 0; j < n; ++j) {
127-
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + grid[i][j];
124+
for (int i = 1; i <= m; ++i) {
125+
for (int j = 1; j <= n; ++j) {
126+
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + grid[i - 1][j - 1];
128127
}
129128
}
130-
int[][] d = new int[m + 1][n + 1];
131-
for (int i = 0; i < m; ++i) {
132-
for (int j = 0; j < n; ++j) {
133-
if (grid[i][j] == 0) {
134-
int x = i + stampHeight, y = j + stampWidth;
135-
if (x <= m && y <= n && s[x][y] - s[x][j] - s[i][y] + s[i][j] == 0) {
136-
d[i][j]++;
137-
d[i][y]--;
138-
d[x][j]--;
139-
d[x][y]++;
140-
}
129+
int[][] d = new int[m + 2][n + 2];
130+
for (int i = 1; i + stampHeight - 1 <= m; ++i) {
131+
for (int j = 1; j + stampWidth - 1 <= n; ++j) {
132+
int x = i + stampHeight - 1, y = j + stampWidth - 1;
133+
if (s[x][y] - s[x][j - 1] - s[i - 1][y] + s[i - 1][j - 1] == 0) {
134+
d[i][j]++;
135+
d[i][y + 1]--;
136+
d[x + 1][j]--;
137+
d[x + 1][y + 1]++;
141138
}
142139
}
143140
}
144-
int[][] cnt = new int[m + 1][n + 1];
145-
for (int i = 0; i < m; ++i) {
146-
for (int j = 0; j < n; ++j) {
147-
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j];
148-
if (grid[i][j] == 0 && cnt[i + 1][j + 1] == 0) {
141+
for (int i = 1; i <= m; ++i) {
142+
for (int j = 1; j <= n; ++j) {
143+
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
144+
if (grid[i - 1][j - 1] == 0 && d[i][j] == 0) {
149145
return false;
150146
}
151147
}
@@ -163,36 +159,120 @@ public:
163159
bool possibleToStamp(vector<vector<int>>& grid, int stampHeight, int stampWidth) {
164160
int m = grid.size(), n = grid[0].size();
165161
vector<vector<int>> s(m + 1, vector<int>(n + 1));
166-
for (int i = 0; i < m; ++i) {
167-
for (int j = 0; j < n; ++j) {
168-
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + grid[i][j];
162+
for (int i = 1; i <= m; ++i) {
163+
for (int j = 1; j <= n; ++j) {
164+
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + grid[i - 1][j - 1];
169165
}
170166
}
171-
vector<vector<int>> d(m + 1, vector<int>(n + 1));
172-
for (int i = 0; i < m; ++i) {
173-
for (int j = 0; j < n; ++j) {
174-
if (grid[i][j]) continue;
175-
int x = i + stampHeight, y = j + stampWidth;
176-
if (x <= m && y <= n && s[x][y] - s[i][y] - s[x][j] + s[i][j] == 0) {
167+
168+
vector<vector<int>> d(m + 2, vector<int>(n + 2));
169+
for (int i = 1; i + stampHeight - 1 <= m; ++i) {
170+
for (int j = 1; j + stampWidth - 1 <= n; ++j) {
171+
int x = i + stampHeight - 1, y = j + stampWidth - 1;
172+
if (s[x][y] - s[x][j - 1] - s[i - 1][y] + s[i - 1][j - 1] == 0) {
177173
d[i][j]++;
178-
d[x][j]--;
179-
d[i][y]--;
180-
d[x][y]++;
174+
d[i][y + 1]--;
175+
d[x + 1][j]--;
176+
d[x + 1][y + 1]++;
181177
}
182178
}
183179
}
184-
vector<vector<int>> cnt(m + 1, vector<int>(n + 1));
185-
for (int i = 0; i < m; ++i) {
186-
for (int j = 0; j < n; ++j) {
187-
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j];
188-
if (grid[i][j] == 0 && cnt[i + 1][j + 1] == 0) return false;
180+
181+
for (int i = 1; i <= m; ++i) {
182+
for (int j = 1; j <= n; ++j) {
183+
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
184+
if (grid[i - 1][j - 1] == 0 && d[i][j] == 0) {
185+
return false;
186+
}
189187
}
190188
}
191189
return true;
192190
}
193191
};
194192
```
195193

194+
### **Go**
195+
196+
```go
197+
func possibleToStamp(grid [][]int, stampHeight int, stampWidth int) bool {
198+
m, n := len(grid), len(grid[0])
199+
s := make([][]int, m+1)
200+
for i := range s {
201+
s[i] = make([]int, n+1)
202+
}
203+
for i := 1; i <= m; i++ {
204+
for j := 1; j <= n; j++ {
205+
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + grid[i-1][j-1]
206+
}
207+
}
208+
209+
d := make([][]int, m+2)
210+
for i := range d {
211+
d[i] = make([]int, n+2)
212+
}
213+
214+
for i := 1; i+stampHeight-1 <= m; i++ {
215+
for j := 1; j+stampWidth-1 <= n; j++ {
216+
x, y := i+stampHeight-1, j+stampWidth-1
217+
if s[x][y]-s[x][j-1]-s[i-1][y]+s[i-1][j-1] == 0 {
218+
d[i][j]++
219+
d[i][y+1]--
220+
d[x+1][j]--
221+
d[x+1][y+1]++
222+
}
223+
}
224+
}
225+
226+
for i := 1; i <= m; i++ {
227+
for j := 1; j <= n; j++ {
228+
d[i][j] += d[i-1][j] + d[i][j-1] - d[i-1][j-1]
229+
if grid[i-1][j-1] == 0 && d[i][j] == 0 {
230+
return false
231+
}
232+
}
233+
}
234+
return true
235+
}
236+
```
237+
238+
### **TypeScript**
239+
240+
```ts
241+
function possibleToStamp(grid: number[][], stampHeight: number, stampWidth: number): boolean {
242+
const m = grid.length;
243+
const n = grid[0].length;
244+
const s: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
245+
for (let i = 1; i <= m; ++i) {
246+
for (let j = 1; j <= n; ++j) {
247+
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + grid[i - 1][j - 1];
248+
}
249+
}
250+
251+
const d: number[][] = Array.from({ length: m + 2 }, () => Array(n + 2).fill(0));
252+
for (let i = 1; i + stampHeight - 1 <= m; ++i) {
253+
for (let j = 1; j + stampWidth - 1 <= n; ++j) {
254+
const [x, y] = [i + stampHeight - 1, j + stampWidth - 1];
255+
if (s[x][y] - s[x][j - 1] - s[i - 1][y] + s[i - 1][j - 1] === 0) {
256+
d[i][j]++;
257+
d[i][y + 1]--;
258+
d[x + 1][j]--;
259+
d[x + 1][y + 1]++;
260+
}
261+
}
262+
}
263+
264+
for (let i = 1; i <= m; ++i) {
265+
for (let j = 1; j <= n; ++j) {
266+
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
267+
if (grid[i - 1][j - 1] === 0 && d[i][j] === 0) {
268+
return false;
269+
}
270+
}
271+
}
272+
return true;
273+
}
274+
```
275+
196276
### **Rust**
197277

198278
```rust
@@ -264,49 +344,6 @@ impl Solution {
264344
}
265345
```
266346

267-
### **Go**
268-
269-
```go
270-
func possibleToStamp(grid [][]int, stampHeight int, stampWidth int) bool {
271-
m, n := len(grid), len(grid[0])
272-
s := make([][]int, m+1)
273-
d := make([][]int, m+1)
274-
cnt := make([][]int, m+1)
275-
for i := range s {
276-
s[i] = make([]int, n+1)
277-
d[i] = make([]int, n+1)
278-
cnt[i] = make([]int, n+1)
279-
}
280-
for i, row := range grid {
281-
for j, v := range row {
282-
s[i+1][j+1] = s[i+1][j] + s[i][j+1] - s[i][j] + v
283-
}
284-
}
285-
for i, row := range grid {
286-
for j, v := range row {
287-
if v == 0 {
288-
x, y := i+stampHeight, j+stampWidth
289-
if x <= m && y <= n && s[x][y]-s[i][y]-s[x][j]+s[i][j] == 0 {
290-
d[i][j]++
291-
d[i][y]--
292-
d[x][j]--
293-
d[x][y]++
294-
}
295-
}
296-
}
297-
}
298-
for i, row := range grid {
299-
for j, v := range row {
300-
cnt[i+1][j+1] = cnt[i+1][j] + cnt[i][j+1] - cnt[i][j] + d[i][j]
301-
if v == 0 && cnt[i+1][j+1] == 0 {
302-
return false
303-
}
304-
}
305-
}
306-
return true
307-
}
308-
```
309-
310347
### **JavaScript**
311348

312349
```js
@@ -319,31 +356,30 @@ func possibleToStamp(grid [][]int, stampHeight int, stampWidth int) bool {
319356
var possibleToStamp = function (grid, stampHeight, stampWidth) {
320357
const m = grid.length;
321358
const n = grid[0].length;
322-
let s = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
323-
let d = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
324-
let cnt = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
325-
for (let i = 0; i < m; ++i) {
326-
for (let j = 0; j < n; ++j) {
327-
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + grid[i][j];
359+
const s = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
360+
for (let i = 1; i <= m; ++i) {
361+
for (let j = 1; j <= n; ++j) {
362+
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + grid[i - 1][j - 1];
328363
}
329364
}
330-
for (let i = 0; i < m; ++i) {
331-
for (let j = 0; j < n; ++j) {
332-
if (grid[i][j] == 0) {
333-
let [x, y] = [i + stampHeight, j + stampWidth];
334-
if (x <= m && y <= n && s[x][y] - s[i][y] - s[x][j] + s[i][j] == 0) {
335-
d[i][j]++;
336-
d[i][y]--;
337-
d[x][j]--;
338-
d[x][y]++;
339-
}
365+
366+
const d = Array.from({ length: m + 2 }, () => Array(n + 2).fill(0));
367+
for (let i = 1; i + stampHeight - 1 <= m; ++i) {
368+
for (let j = 1; j + stampWidth - 1 <= n; ++j) {
369+
const [x, y] = [i + stampHeight - 1, j + stampWidth - 1];
370+
if (s[x][y] - s[x][j - 1] - s[i - 1][y] + s[i - 1][j - 1] === 0) {
371+
d[i][j]++;
372+
d[i][y + 1]--;
373+
d[x + 1][j]--;
374+
d[x + 1][y + 1]++;
340375
}
341376
}
342377
}
343-
for (let i = 0; i < m; ++i) {
344-
for (let j = 0; j < n; ++j) {
345-
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j];
346-
if (grid[i][j] == 0 && cnt[i + 1][j + 1] == 0) {
378+
379+
for (let i = 1; i <= m; ++i) {
380+
for (let j = 1; j <= n; ++j) {
381+
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
382+
if (grid[i - 1][j - 1] === 0 && d[i][j] === 0) {
347383
return false;
348384
}
349385
}
@@ -352,14 +388,6 @@ var possibleToStamp = function (grid, stampHeight, stampWidth) {
352388
};
353389
```
354390

355-
### **TypeScript**
356-
357-
<!-- 这里可写当前语言的特殊实现逻辑 -->
358-
359-
```ts
360-
361-
```
362-
363391
### **...**
364392

365393
```

0 commit comments

Comments
 (0)