Skip to content

Commit 5d60bc5

Browse files
committed
feat: add solutions to lc problem: No.2617
No.2617.Minimum Number of Visited Cells in a Grid
1 parent 9c67122 commit 5d60bc5

File tree

6 files changed

+342
-247
lines changed

6 files changed

+342
-247
lines changed

solution/2600-2699/2617.Minimum Number of Visited Cells in a Grid/README.md

+119-86
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,19 @@
6363

6464
<!-- 这里可写通用的实现逻辑 -->
6565

66-
**方法一:BFS**
66+
**方法一:优先队列**
6767

68-
我们用 $row[i]$ 表示第 $i$ 行已经访问到的最右边的列,用 $col[j]$ 表示第 $j$ 列已经访问到的最下边的行。初始时,$row[0] = col[0] = 0$。
68+
我们记网格的行数为 $m$,列数为 $n$,定义 $dist[i][j]$ 表示从坐标 $(0, 0)$ 移动到坐标 $(i, j)$ 的最短距离,初始时 $dist[0][0] = 1$,其它 $dist[i][j]=-1$。
6969

70-
接下来,我们定义一个队列,用于存储当前可以访问的格子。队列中的元素为一个三元组 $(dist, i, j)$,表示从起点 $(0, 0)$ 到达 $(i, j)$ 的最短距离为 $dist$。初始时,我们将 $(1, 0, 0)$ 加入队列中
70+
对于每个格子 $(i, j)$,它可以从上边或者左边的格子移动过来。如果是从上边的格子 $(i', j)$ 移动过来,其中 $0 \leq i' \lt i$,那么 $(i', j)$ 需要满足 $grid[i'][j] + i' \geq i$,我们要从这些格子中选择一个距离最近的格子
7171

72-
在每一步中,我们从队首取出一个元素 $(dist, i, j)$,如果 $(i, j)$ 为终点,则直接返回 $dist$。否则,我们将 $(i, j)$ 右边的格子加入队列中,其中右边的格子的下标范围为 $[max(row[i], j) + 1, min(n, j + grid[i][j] + 1))$。同理,我们将 $(i, j)$ 下边的格子加入队列中,其中下边的格子的下标范围为 $[max(col[j], i) + 1, min(m, i + grid[i][j] + 1))$。加入格子后,我们需要更新 $row[i]$ 和 $col[j]$
72+
因此,我们可以对每一列 $j$ 维护一个优先队列(小根堆),优先队列中每个元素是一个二元组 $(dist[i][j], i)$,表示从坐标 $(0, 0)$ 移动到坐标 $(i, j)$ 的最短距离为 $dist[i][j]$。当我们考虑坐标 $(i, j)$ 时,我们只需要从优先队列中取出队头元素 $(dist[i'][j], i')$,如果 $grid[i'][j] + i' \geq i$,那么就可以从坐标 $(i', j)$ 移动到坐标 $(i, j)$,此时我们就可以更新 $dist[i][j]$ 的值,即 $dist[i][j] = dist[i'][j] + 1$,并将 $(dist[i][j], i)$ 加入到优先队列中
7373

74-
最后,如果我们遍历完整个队列都没有找到终点,则说明无法到达终点,返回 $-1$
74+
同理,我们可以对每一行 $i$ 维护一个优先队列,然后进行与上述类似的操作
7575

76-
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为网格的行数和列数。
76+
最终,我们可以得到从坐标 $(0, 0)$ 移动到坐标 $(m - 1, n - 1)$ 的最短距离 $dist[m - 1][n - 1]$,即为答案。
77+
78+
时间复杂度 $O(m \times n \times \log (m \times n))$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为网格的行数和列数。
7779

7880
<!-- tabs:start -->
7981

@@ -85,20 +87,24 @@
8587
class Solution:
8688
def minimumVisitedCells(self, grid: List[List[int]]) -> int:
8789
m, n = len(grid), len(grid[0])
88-
row = [0] * m
89-
col = [0] * n
90-
q = deque([(1, 0, 0)])
91-
while q:
92-
dist, i, j = q.popleft()
93-
if i == m - 1 and j == n - 1:
94-
return dist
95-
for k in range(max(row[i], j) + 1, min(n, j + grid[i][j] + 1)):
96-
q.append((dist + 1, i, k))
97-
row[i] = k
98-
for k in range(max(col[j], i) + 1, min(m, i + grid[i][j] + 1)):
99-
q.append((dist + 1, k, j))
100-
col[j] = k
101-
return -1
90+
dist = [[-1] * n for _ in range(m)]
91+
dist[0][0] = 1
92+
row = [[] for _ in range(m)]
93+
col = [[] for _ in range(n)]
94+
for i in range(m):
95+
for j in range(n):
96+
while row[i] and grid[i][row[i][0][1]] + row[i][0][1] < j:
97+
heappop(row[i])
98+
if row[i] and (dist[i][j] == -1 or dist[i][j] > row[i][0][0] + 1):
99+
dist[i][j] = row[i][0][0] + 1
100+
while col[j] and grid[col[j][0][1]][j] + col[j][0][1] < i:
101+
heappop(col[j])
102+
if col[j] and (dist[i][j] == -1 or dist[i][j] > col[j][0][0] + 1):
103+
dist[i][j] = col[j][0][0] + 1
104+
if dist[i][j] != -1:
105+
heappush(row[i], (dist[i][j], j))
106+
heappush(col[j], (dist[i][j], i))
107+
return dist[-1][-1]
102108
```
103109

104110
### **Java**
@@ -109,28 +115,38 @@ class Solution:
109115
class Solution {
110116
public int minimumVisitedCells(int[][] grid) {
111117
int m = grid.length, n = grid[0].length;
112-
int[] row = new int[m];
113-
int[] col = new int[n];
114-
Deque<int[]> q = new ArrayDeque<>();
115-
q.offer(new int[] {1, 0, 0});
116-
while (!q.isEmpty()) {
117-
int[] p = q.poll();
118-
int i = p[1], j = p[2], dist = p[0];
119-
if (i == m - 1 && j == n - 1) {
120-
return dist;
121-
}
122-
int k = Math.max(row[i], j) + 1;
123-
for (; k < Math.min(n, j + grid[i][j] + 1); ++k) {
124-
q.offer(new int[] {dist + 1, i, k});
125-
row[i] = k;
126-
}
127-
k = Math.max(col[j], i) + 1;
128-
for (; k < Math.min(m, i + grid[i][j] + 1); ++k) {
129-
q.offer(new int[] {dist + 1, k, j});
130-
col[j] = k;
118+
int[][] dist = new int[m][n];
119+
PriorityQueue<int[]>[] row = new PriorityQueue[m];
120+
PriorityQueue<int[]>[] col = new PriorityQueue[n];
121+
for (int i = 0; i < m; ++i) {
122+
Arrays.fill(dist[i], -1);
123+
row[i] = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
124+
}
125+
for (int i = 0; i < n; ++i) {
126+
col[i] = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
127+
}
128+
dist[0][0] = 1;
129+
for (int i = 0; i < m; ++i) {
130+
for (int j = 0; j < n; ++j) {
131+
while (!row[i].isEmpty() && grid[i][row[i].peek()[1]] + row[i].peek()[1] < j) {
132+
row[i].poll();
133+
}
134+
if (!row[i].isEmpty() && (dist[i][j] == -1 || row[i].peek()[0] + 1 < dist[i][j])) {
135+
dist[i][j] = row[i].peek()[0] + 1;
136+
}
137+
while (!col[j].isEmpty() && grid[col[j].peek()[1]][j] + col[j].peek()[1] < i) {
138+
col[j].poll();
139+
}
140+
if (!col[j].isEmpty() && (dist[i][j] == -1 || col[j].peek()[0] + 1 < dist[i][j])) {
141+
dist[i][j] = col[j].peek()[0] + 1;
142+
}
143+
if (dist[i][j] != -1) {
144+
row[i].offer(new int[]{dist[i][j], j});
145+
col[j].offer(new int[]{dist[i][j], i});
146+
}
131147
}
132148
}
133-
return -1;
149+
return dist[m - 1][n - 1];
134150
}
135151
}
136152
```
@@ -142,27 +158,32 @@ class Solution {
142158
public:
143159
int minimumVisitedCells(vector<vector<int>>& grid) {
144160
int m = grid.size(), n = grid[0].size();
145-
int row[m], col[n];
146-
memset(row, 0, sizeof(row));
147-
memset(col, 0, sizeof(col));
148-
queue<tuple<int, int, int>> q;
149-
q.emplace(1, 0, 0);
150-
while (!q.empty()) {
151-
auto [dist, i, j] = q.front();
152-
q.pop();
153-
if (i == m - 1 && j == n - 1) {
154-
return dist;
155-
}
156-
for (int k = max(row[i], j) + 1; k < min(n, j + grid[i][j] + 1); ++k) {
157-
q.emplace(dist + 1, i, k);
158-
row[i] = k;
159-
}
160-
for (int k = max(col[j], i) + 1; k < min(m, i + grid[i][j] + 1); ++k) {
161-
q.emplace(dist + 1, k, j);
162-
col[j] = k;
161+
vector<vector<int>> dist(m, vector<int>(n, -1));
162+
using pii = pair<int, int>;
163+
priority_queue<pii, vector<pii>, greater<pii>> row[m];
164+
priority_queue<pii, vector<pii>, greater<pii>> col[n];
165+
dist[0][0] = 1;
166+
for (int i = 0; i < m; ++i) {
167+
for (int j = 0; j < n; ++j) {
168+
while (!row[i].empty() && grid[i][row[i].top().second] + row[i].top().second < j) {
169+
row[i].pop();
170+
}
171+
if (!row[i].empty() && (dist[i][j] == -1 || row[i].top().first + 1 < dist[i][j])) {
172+
dist[i][j] = row[i].top().first + 1;
173+
}
174+
while (!col[j].empty() && grid[col[j].top().second][j] + col[j].top().second < i) {
175+
col[j].pop();
176+
}
177+
if (!col[j].empty() && (dist[i][j] == -1 || col[j].top().first + 1 < dist[i][j])) {
178+
dist[i][j] = col[j].top().first + 1;
179+
}
180+
if (dist[i][j] != -1) {
181+
row[i].emplace(dist[i][j], j);
182+
col[j].emplace(dist[i][j], i);
183+
}
163184
}
164185
}
165-
return -1;
186+
return dist[m - 1][n - 1];
166187
}
167188
};
168189
```
@@ -172,41 +193,53 @@ public:
172193
```go
173194
func minimumVisitedCells(grid [][]int) int {
174195
m, n := len(grid), len(grid[0])
175-
row := make([]int, m)
176-
col := make([]int, n)
177-
q := [][3]int{{1, 0, 0}}
178-
for len(q) > 0 {
179-
p := q[0]
180-
dist, i, j := p[0], p[1], p[2]
181-
if i == m-1 && j == n-1 {
182-
return dist
183-
}
184-
q = q[1:]
185-
for k := max(row[i], j) + 1; k < min(n, j+grid[i][j]+1); k++ {
186-
q = append(q, [3]int{dist + 1, i, k})
187-
row[i] = k
196+
dist := make([][]int, m)
197+
row := make([]hp, m)
198+
col := make([]hp, n)
199+
for i := range dist {
200+
dist[i] = make([]int, n)
201+
for j := range dist[i] {
202+
dist[i][j] = -1
188203
}
189-
for k := max(col[j], i) + 1; k < min(m, i+grid[i][j]+1); k++ {
190-
q = append(q, [3]int{dist + 1, k, j})
191-
col[j] = k
204+
}
205+
dist[0][0] = 1
206+
for i := 0; i < m; i++ {
207+
for j := 0; j < n; j++ {
208+
for len(row[i]) > 0 && grid[i][row[i][0].second]+row[i][0].second < j {
209+
heap.Pop(&row[i])
210+
}
211+
if len(row[i]) > 0 && (dist[i][j] == -1 || row[i][0].first+1 < dist[i][j]) {
212+
dist[i][j] = row[i][0].first + 1
213+
}
214+
for len(col[j]) > 0 && grid[col[j][0].second][j]+col[j][0].second < i {
215+
heap.Pop(&col[j])
216+
}
217+
if len(col[j]) > 0 && (dist[i][j] == -1 || col[j][0].first+1 < dist[i][j]) {
218+
dist[i][j] = col[j][0].first + 1
219+
}
220+
if dist[i][j] != -1 {
221+
heap.Push(&row[i], pair{dist[i][j], j})
222+
heap.Push(&col[j], pair{dist[i][j], i})
223+
}
192224
}
193225
}
194-
return -1
226+
return dist[m-1][n-1]
195227
}
196228
197-
func max(a, b int) int {
198-
if a > b {
199-
return a
200-
}
201-
return b
229+
type pair struct {
230+
first int
231+
second int
202232
}
203233
204-
func min(a, b int) int {
205-
if a < b {
206-
return a
207-
}
208-
return b
234+
type hp []pair
235+
236+
func (a hp) Len() int { return len(a) }
237+
func (a hp) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
238+
func (a hp) Less(i, j int) bool {
239+
return a[i].first < a[j].first || (a[i].first == a[j].first && a[i].second < a[j].second)
209240
}
241+
func (a *hp) Push(x interface{}) { *a = append(*a, x.(pair)) }
242+
func (a *hp) Pop() interface{} { l := len(*a); t := (*a)[l-1]; *a = (*a)[:l-1]; return t }
210243
```
211244

212245
### **...**

0 commit comments

Comments
 (0)