Skip to content

feat: add solutions to lc problem: No.2132 #2092

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
302 changes: 165 additions & 137 deletions solution/2100-2199/2132.Stamping the Grid/README.md
Original file line number Diff line number Diff line change
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
Loading