60
60
61
61
** 方法一:二维前缀和 + 二维差分**
62
62
63
- 根据题给的约束,很容易推出,一个格子能贴邮票的条件为,在加上邮票的长和宽后,右下角不越界的情况下,当前子区域中所有格子的和为 0 。
63
+ 根据题目描述,每一个空格子都必须被邮票覆盖,而且不能覆盖任何被占据的格子。因此,我们可以遍历二维矩阵,对于每个格子,如果以该格子为左上角的 $stampHeight \times stampWidth$ 的区域内的所有格子都是空格子(即没有被占据),那么我们就可以在该格子处放置一个邮票 。
64
64
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}$ 。
66
66
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$ 来记录这一变化。即:
68
68
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
+ $$
70
77
71
- 需要注意的是二维数组的下标关系,具体参考如下 。
78
+ 最后,我们对二维差分数组 $d$ 进行前缀和运算,可以得出每个格子被邮票覆盖的次数。如果某个格子没有被占据,且被邮票覆盖的次数为 $0$,那么我们就无法将邮票放置在该格子处,因此我们需要返回 $\texttt{false}$。如果所有“没被占据的格子”都成功被邮票覆盖,返回 $\texttt{true}$ 。
72
79
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$ 分别是二维矩阵的高度和宽度。
78
81
79
82
<!-- tabs:start -->
80
83
@@ -89,26 +92,22 @@ class Solution:
89
92
) -> bool :
90
93
m, n = len (grid), len (grid[0 ])
91
94
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 :
112
111
return False
113
112
return True
114
113
```
@@ -122,30 +121,27 @@ class Solution {
122
121
public boolean possibleToStamp (int [][] grid , int stampHeight , int stampWidth ) {
123
122
int m = grid. length, n = grid[0 ]. length;
124
123
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 ];
128
127
}
129
128
}
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 ]++ ;
141
138
}
142
139
}
143
140
}
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 ) {
149
145
return false ;
150
146
}
151
147
}
@@ -163,36 +159,120 @@ public:
163
159
bool possibleToStamp(vector<vector<int >>& grid, int stampHeight, int stampWidth) {
164
160
int m = grid.size(), n = grid[ 0] .size();
165
161
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 ] ;
169
165
}
170
166
}
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) {
177
173
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 ]++;
181
177
}
182
178
}
183
179
}
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
+ }
189
187
}
190
188
}
191
189
return true;
192
190
}
193
191
};
194
192
```
195
193
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
+
196
276
### ** Rust**
197
277
198
278
``` rust
@@ -264,49 +344,6 @@ impl Solution {
264
344
}
265
345
```
266
346
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
-
310
347
### ** JavaScript**
311
348
312
349
``` js
@@ -319,31 +356,30 @@ func possibleToStamp(grid [][]int, stampHeight int, stampWidth int) bool {
319
356
var possibleToStamp = function (grid , stampHeight , stampWidth ) {
320
357
const m = grid .length ;
321
358
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 ];
328
363
}
329
364
}
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 ] ++ ;
340
375
}
341
376
}
342
377
}
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 ) {
347
383
return false ;
348
384
}
349
385
}
@@ -352,14 +388,6 @@ var possibleToStamp = function (grid, stampHeight, stampWidth) {
352
388
};
353
389
```
354
390
355
- ### ** TypeScript**
356
-
357
- <!-- 这里可写当前语言的特殊实现逻辑 -->
358
-
359
- ``` ts
360
-
361
- ```
362
-
363
391
### ** ...**
364
392
365
393
```
0 commit comments