63
63
64
64
<!-- 这里可写通用的实现逻辑 -->
65
65
66
- ** 方法一:BFS **
66
+ ** 方法一:优先队列 **
67
67
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 $。
69
69
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$,我们要从这些格子中选择一个距离最近的格子 。
71
71
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)$ 加入到优先队列中 。
73
73
74
- 最后,如果我们遍历完整个队列都没有找到终点,则说明无法到达终点,返回 $-1$ 。
74
+ 同理,我们可以对每一行 $i$ 维护一个优先队列,然后进行与上述类似的操作 。
75
75
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$ 分别为网格的行数和列数。
77
79
78
80
<!-- tabs:start -->
79
81
85
87
class Solution :
86
88
def minimumVisitedCells (self , grid : List[List[int ]]) -> int :
87
89
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 ]
102
108
```
103
109
104
110
### ** Java**
@@ -109,28 +115,38 @@ class Solution:
109
115
class Solution {
110
116
public int minimumVisitedCells (int [][] grid ) {
111
117
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
+ }
131
147
}
132
148
}
133
- return - 1 ;
149
+ return dist[m - 1 ][n - 1 ] ;
134
150
}
135
151
}
136
152
```
@@ -142,27 +158,32 @@ class Solution {
142
158
public:
143
159
int minimumVisitedCells(vector<vector<int >>& grid) {
144
160
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
+ }
163
184
}
164
185
}
165
- return -1 ;
186
+ return dist [ m - 1 ] [ n - 1 ] ;
166
187
}
167
188
};
168
189
```
@@ -172,41 +193,53 @@ public:
172
193
```go
173
194
func minimumVisitedCells(grid [][]int) int {
174
195
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
188
203
}
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
+ }
192
224
}
193
225
}
194
- return -1
226
+ return dist[m-1][n-1]
195
227
}
196
228
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
202
232
}
203
233
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)
209
240
}
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 }
210
243
```
211
244
212
245
### ** ...**
0 commit comments