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 {
319356var 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