核心思想
比較直觀的想法就是BFS,但是每次遍歷能走的點(右走,下走)會超時
考慮用兩個set陣列,
TreeSet<Integer>[] R = new TreeSet[n]; TreeSet<Integer>[] C = new TreeSet[m];
R[i]表示第i行還剩下哪些列col沒去過,那麼遍歷就變為了二分查詢第一個比當前j大的col
當col > j + grid[i][j]
時break
TODO:iterator
public int minimumVisitedCells(int[][] grid) {
// n 行 m 列
int n = grid.length, m = grid[0].length;
//儲存步數
int[][] f = new int[n][m];
// 使用雙重迴圈來填充二維陣列
for (int i = 0; i < n; i++) {
Arrays.fill(f[i], -1);
}
TreeSet<Integer>[] R = new TreeSet[n];
TreeSet<Integer>[] C = new TreeSet[m];
for(int i = 0; i < n; i++)
R[i] = new TreeSet<Integer>();
for(int j = 0; j < m; j++)
C[j] = new TreeSet<Integer>();
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(i + j > 0){
R[i].add(j);
C[j].add(i);
}
}
}
Queue<int[]> q = new ArrayDeque<>();
q.offer(new int[]{0, 0});
f[0][0] = 1;
while(!q.isEmpty()){
int[] tp = q.poll();
int i = tp[0], j = tp[1];
// 向右走 去R中找
// 第一個大於j的數
Integer ceil = R[i].ceiling(j);
if(ceil != null){
//最遠距離
int maxiCol = j + grid[i][j];
Iterator<Integer> iterator = R[i].tailSet(ceil).iterator();
while(iterator.hasNext()){
int col = iterator.next();
if (col > maxiCol)
break;
//記錄步數
f[i][col] = f[i][j] + 1;
//推入佇列
q.offer(new int[]{i, col});
//移出Set
iterator.remove();
C[col].remove(i);
}
}
// 向下走 去C中
// 第一個大於i的數
ceil = C[j].ceiling(i);
if(ceil != null){
//最遠距離
int maxiRow = i + grid[i][j];
Iterator<Integer> iterator = C[j].tailSet(ceil).iterator();
while(iterator.hasNext()){
int row = iterator.next();
if(row > maxiRow)
break;
//記錄步數
f[row][j] = f[i][j] + 1;
//推入佇列
q.offer(new int[]{row, j});
//移出Set
iterator.remove();
R[row].remove(j);
}
}
}
return f[n-1][m-1];
}