Expand Up
@@ -60,21 +60,24 @@
**方法一:二维前缀和 + 二维差分**
根据题给的约束,很容易推出,一个格子能贴邮票的条件为,在加上邮票的长和宽后,右下角不越界的情况下,当前子区域中所有格子的和为 0 。
根据题目描述,每一个空格子都必须被邮票覆盖,而且不能覆盖任何被占据的格子。因此,我们可以遍历二维矩阵,对于每个格子,如果以该格子为左上角的 $stampHeight \times stampWidth$ 的区域内的所有格子都是空格子(即没有被占据),那么我们就可以在该格子处放置一个邮票 。
那么显然我们可以维护一个二维的前缀和数组,在 `O(1)` 的时间复杂度下就可以判断每次遍历到的格子是否能贴邮票 。
为了快速判断一个区域内的所有格子是否都是空格子,我们可以使用二维前缀和。我们用 $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}$ 。
而因为贴邮票的操作,可以概括为将当前子区域的所有格子的值都置为 `1`,很自然的就能想到用一个二维的差分数组来维护贴邮票后的状态。
那么以 $(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$ 来记录这一变化。即:
最后只要对该差分数组再求一次二维前缀和,只要当前格子的和为 `0`,就意味着存在没有覆盖完全的情况,直接返回 `false` 即可。
$$
\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}
$$
需要注意的是二维数组的下标关系,具体参考如下 。
最后,我们对二维差分数组 $d$ 进行前缀和运算,可以得出每个格子被邮票覆盖的次数。如果某个格子没有被占据,且被邮票覆盖的次数为 0ドル,ドル那么我们就无法将邮票放置在该格子处,因此我们需要返回 $\texttt{false}$。如果所有"没被占据的格子"都成功被邮票覆盖,返回 $\texttt{true}$ 。
`s[i + 1][j + 1]` 表示第 i 行第 j 列左上部分所有元素之和,其中 i, j 下标从 0 开始。
则 `s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + nums[i][j]`。
以 (x1, y1) 为左上角,(x2, y2) 为右下角的子矩阵和 `sub = s[x2 + 1][y2 + 1] - s[x2 + 1][y1] - s[x1][y2 + 1] + s[x1][y1]`。
时间复杂度 $O(m \times n),ドル空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是二维矩阵的高度和宽度。
<!-- tabs:start -->
Expand All
@@ -89,26 +92,22 @@ class Solution:
) -> bool:
m, n = len(grid), len(grid[0])
s = [[0] * (n + 1) for _ in range(m + 1)]
for i, row in enumerate(grid):
for j, v in enumerate(row):
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + v
d = [[0] * (n + 1) for _ in range(m + 1)]
for i, row in enumerate(grid):
for j, v in enumerate(row):
if v == 0:
x, y = i + stampHeight, j + stampWidth
if x <= m and y <= n and s[x][y] - s[x][j] - s[i][y] + s[i][j] == 0:
d[i][j] += 1
d[i][y] -= 1
d[x][j] -= 1
d[x][y] += 1
cnt = [[0] * (n + 1) for _ in range(m + 1)]
for i, row in enumerate(grid):
for j, v in enumerate(row):
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j]
if v == 0 and cnt[i + 1][j + 1] == 0:
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
```
Expand All
@@ -122,30 +121,27 @@ class Solution {
public boolean possibleToStamp(int[][] grid, int stampHeight, int stampWidth) {
int m = grid.length, n = grid[0].length;
int[][] s = new int[m + 1][n + 1];
for (int i = 0 ; i < m; ++i) {
for (int j = 0 ; j < n; ++j) {
s[i + 1 ][j + 1 ] = s[i + 1][j] + s[i][j + 1] - s[i][j] + grid[i][j];
for (int i = 1 ; i <= m; ++i) {
for (int j = 1 ; j <= n; ++j) {
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1 ][j - 1 ] + grid[i - 1 ][j - 1 ];
}
}
int[][] d = new int[m + 1][n + 1];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 0) {
int x = i + stampHeight, y = j + stampWidth;
if (x <= m && y <= n && s[x][y] - s[x][j] - s[i][y] + s[i][j] == 0) {
d[i][j]++;
d[i][y]--;
d[x][j]--;
d[x][y]++;
}
int[][] d = new int[m + 2][n + 2];
for (int i = 1; i + stampHeight - 1 <= m; ++i) {
for (int j = 1; j + stampWidth - 1 <= n; ++j) {
int x = i + stampHeight - 1, y = j + stampWidth - 1;
if (s[x][y] - s[x][j - 1] - s[i - 1][y] + s[i - 1][j - 1] == 0) {
d[i][j]++;
d[i][y + 1]--;
d[x + 1][j]--;
d[x + 1][y + 1]++;
}
}
}
int[][] cnt = new int[m + 1][n + 1];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j];
if (grid[i][j] == 0 && cnt[i + 1][j + 1] == 0) {
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
if (grid[i - 1][j - 1] == 0 && d[i][j] == 0) {
return false;
}
}
Expand All
@@ -163,36 +159,120 @@ public:
bool possibleToStamp(vector<vector<int>>& grid, int stampHeight, int stampWidth) {
int m = grid.size(), n = grid[0].size();
vector<vector<int>> s(m + 1, vector<int>(n + 1));
for (int i = 0 ; i < m; ++i) {
for (int j = 0 ; j < n; ++j) {
s[i + 1 ][j + 1 ] = s[i + 1][j] + s[i][j + 1] - s[i][j] + grid[i][j];
for (int i = 1 ; i <= m; ++i) {
for (int j = 1 ; j <= n; ++j) {
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1 ][j - 1 ] + grid[i - 1 ][j - 1 ];
}
}
vector<vector<int>> d(m + 1, vector<int>(n + 1));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n ; ++j ) {
if (grid[i][j]) continue;
int x = i + stampHeight, y = j + stampWidth;
if (x <= m && y <= n && s[x][y] - s[i][y ] - s[x][j ] + s[i][j] == 0) {
vector<vector<int>> d(m + 2, vector<int>(n + 2));
for (int i = 1; i + stampHeight - 1 <= m ; ++i ) {
for (int j = 1; j + stampWidth - 1 <= n; ++j) {
int x = i + stampHeight - 1 , y = j + stampWidth - 1 ;
if (s[x][y] - s[x][j - 1 ] - s[i - 1][y ] + s[i - 1 ][j - 1 ] == 0) {
d[i][j]++;
d[x][j ]--;
d[i][y ]--;
d[x][y]++;
d[i][y + 1 ]--;
d[x + 1][j ]--;
d[x + 1 ][y + 1 ]++;
}
}
}
vector<vector<int>> cnt(m + 1, vector<int>(n + 1));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j];
if (grid[i][j] == 0 && cnt[i + 1][j + 1] == 0) return false;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
if (grid[i - 1][j - 1] == 0 && d[i][j] == 0) {
return false;
}
}
}
return true;
}
};
```
### **Go**
```go
func possibleToStamp(grid [][]int, stampHeight int, stampWidth int) bool {
m, n := len(grid), len(grid[0])
s := make([][]int, m+1)
for i := range s {
s[i] = make([]int, n+1)
}
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + grid[i-1][j-1]
}
}
d := make([][]int, m+2)
for i := range d {
d[i] = make([]int, n+2)
}
for i := 1; i+stampHeight-1 <= m; i++ {
for j := 1; j+stampWidth-1 <= n; j++ {
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]++
d[i][y+1]--
d[x+1][j]--
d[x+1][y+1]++
}
}
}
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
d[i][j] += d[i-1][j] + d[i][j-1] - d[i-1][j-1]
if grid[i-1][j-1] == 0 && d[i][j] == 0 {
return false
}
}
}
return true
}
```
### **TypeScript**
```ts
function possibleToStamp(grid: number[][], stampHeight: number, stampWidth: number): boolean {
const m = grid.length;
const n = grid[0].length;
const s: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
for (let i = 1; i <= m; ++i) {
for (let j = 1; j <= n; ++j) {
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + grid[i - 1][j - 1];
}
}
const d: number[][] = Array.from({ length: m + 2 }, () => Array(n + 2).fill(0));
for (let i = 1; i + stampHeight - 1 <= m; ++i) {
for (let j = 1; j + stampWidth - 1 <= n; ++j) {
const [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]++;
d[i][y + 1]--;
d[x + 1][j]--;
d[x + 1][y + 1]++;
}
}
}
for (let i = 1; i <= m; ++i) {
for (let j = 1; j <= n; ++j) {
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
if (grid[i - 1][j - 1] === 0 && d[i][j] === 0) {
return false;
}
}
}
return true;
}
```
### **Rust**
```rust
Expand Down
Expand Up
@@ -264,49 +344,6 @@ impl Solution {
}
```
### **Go**
```go
func possibleToStamp(grid [][]int, stampHeight int, stampWidth int) bool {
m, n := len(grid), len(grid[0])
s := make([][]int, m+1)
d := make([][]int, m+1)
cnt := make([][]int, m+1)
for i := range s {
s[i] = make([]int, n+1)
d[i] = make([]int, n+1)
cnt[i] = make([]int, n+1)
}
for i, row := range grid {
for j, v := range row {
s[i+1][j+1] = s[i+1][j] + s[i][j+1] - s[i][j] + v
}
}
for i, row := range grid {
for j, v := range row {
if v == 0 {
x, y := i+stampHeight, j+stampWidth
if x <= m && y <= n && s[x][y]-s[i][y]-s[x][j]+s[i][j] == 0 {
d[i][j]++
d[i][y]--
d[x][j]--
d[x][y]++
}
}
}
}
for i, row := range grid {
for j, v := range row {
cnt[i+1][j+1] = cnt[i+1][j] + cnt[i][j+1] - cnt[i][j] + d[i][j]
if v == 0 && cnt[i+1][j+1] == 0 {
return false
}
}
}
return true
}
```
### **JavaScript**
```js
Expand All
@@ -319,31 +356,30 @@ func possibleToStamp(grid [][]int, stampHeight int, stampWidth int) bool {
var possibleToStamp = function (grid, stampHeight, stampWidth) {
const m = grid.length;
const n = grid[0].length;
let s = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
let d = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
let cnt = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
s[i + 1][j + 1] = s[i + 1][j] + s[i][j + 1] - s[i][j] + grid[i][j];
const s = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
for (let i = 1; i <= m; ++i) {
for (let j = 1; j <= n; ++j) {
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + grid[i - 1][j - 1];
}
}
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
if (grid[i][j] == 0 ) {
let [x, y] = [i + stampHeight, j + stampWidth];
if (x <= m && y <= n && s[x][y] - s[i][y] - s[x][j] + s[i][j] == 0) {
d[i ][j]++;
d[i][y]-- ;
d[x][j ]--;
d[x][y]++ ;
}
const d = Array.from({ length: m + 2 }, () => Array(n + 2).fill(0));
for (let i = 1; i + stampHeight - 1 <= m; ++i ) {
for (let j = 1; j + stampWidth - 1 <= n; ++j) {
const [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]++ ;
d[i][y + 1 ]--;
d[x + 1][j]-- ;
d[x + 1][y + 1]++;
}
}
}
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
cnt[i + 1][j + 1] = cnt[i + 1][j] + cnt[i][j + 1] - cnt[i][j] + d[i][j];
if (grid[i][j] == 0 && cnt[i + 1][j + 1] == 0) {
for (let i = 1; i <= m; ++i) {
for (let j = 1; j <= n; ++j) {
d[i][j] += d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
if (grid[i - 1][j - 1] === 0 && d[i][j] === 0) {
return false;
}
}
Expand All
@@ -352,14 +388,6 @@ var possibleToStamp = function (grid, stampHeight, stampWidth) {
};
```
### **TypeScript**
<!-- 这里可写当前语言的特殊实现逻辑 -->
```ts
```
### **...**
```
Expand Down