题目的提示grid[i][j] 位于区间 [0, ..., N*N - 1] 内。所以想到的是遍历 0 到N*N-1 如果满足就返回
先定义一个满足优先队列的bean
static class Tmo implements Comparable<Tmo> { public int x; public int y; public int value; public Tmo(int x, int y, int value) { this.x = x; this.y = y; this.value = value; } @Override public int compareTo(Tmo o) { return this.value -o.value; } }
这样的话代码如下
1 public static int swimInWater(int[][] grid) { 2 3 int[][] forward = new int[][]{{0,1},{1,0},{0,-1},{-1,0}}; 4 5 6 int n = grid.length; 7 int len = n*n-1; 8 for (int i = 0; i <= len; i++) { 9 //如果有满足K的就返回 10 int k = i; 11 PriorityQueue<Tmo> pq = new PriorityQueue<>(); 12 pq.offer(new Tmo(0,0,grid[0][0])); 13 14 int[][] exist = new int[n][n]; 15 exist[0][0] = 1; 16 17 while (!pq.isEmpty()){ 18 Tmo poll = pq.poll(); 19 int x = poll.x; 20 int y = poll.y; 21 //朝着四个方向出发 选择短路径 如果结果是N,N则返回 22 for (int j = 0; j < forward.length && poll.value <= k; j++) { 23 //控制方向 24 int[] forw = forward[j]; 25 int tx = x+forw[0]; 26 int ty = y+forw[1]; 27 if (tx <0 || tx >= n || ty <0 || ty >= n || exist[tx][ty] == 1 || grid[tx][ty] > k ){ 28 continue; 29 } 30 if (tx == n-1 && ty == n-1 ){ 31 return k; 32 } 33 exist[tx][ty] = 1; 34 pq.offer(new Tmo(tx,ty,grid[tx][ty])); 35 36 } 37 38 } 39 40 41 42 } 43 44 45 46 return -1; 47 } 48 49
这样算下来需要遍历从0开始一直遍历到符合的。然后可以改为二分查找法来找到那个合适的
1 public static int swimInWater(int[][] grid) { 2 3 int[][] forward = new int[][]{{0,1},{1,0},{0,-1},{-1,0}}; 4 5 6 int n = grid.length; 7 int start = 0; 8 int end = n*n-1; 9 while (start <= end){ 10 //如果有满足K的就返回 11 int middle = (end + start)/2; 12 13 PriorityQueue<Tmo> pq = new PriorityQueue<>(); 14 pq.offer(new Tmo(0,0,grid[0][0])); 15 16 int[][] exist = new int[n][n]; 17 exist[0][0] = 1; 18 boolean search = false; 19 while (!pq.isEmpty()){ 20 Tmo poll = pq.poll(); 21 int x = poll.x; 22 int y = poll.y; 23 //朝着四个方向出发 选择短路径 如果结果是N,N则返回 24 for (int j = 0; j < forward.length && poll.value <= middle; j++) { 25 //控制方向 26 int[] forw = forward[j]; 27 int tx = x+forw[0]; 28 int ty = y+forw[1]; 29 if (tx <0 || tx >= n || ty <0 || ty >= n || exist[tx][ty] == 1 || grid[tx][ty] > middle ){ 30 continue; 31 } 32 if (tx == n-1 && ty == n-1 ){ 33 search = true; 34 break; 35 } 36 exist[tx][ty] = 1; 37 pq.offer(new Tmo(tx,ty,grid[tx][ty])); 38 39 } 40 41 } 42 if (search){ 43 //当前点符合 就寻找小的是不是有符合的 44 end = middle-1; 45 }else { 46 start = middle +1; 47 } 48 } 49 50 51 52 return start; 53 } 54 55
不过上面两种方式遍历time进行BFS,如果值没有限制的话就没法这样做。所以可以换个思路就是从0,0开始每次找到周围最小的然后继续查找,这样保证到最后找到结果时路径里的最大值是最小的。
public static int swimInWater2(int[][] grid) { int[][] forward = new int[][]{{0,1},{1,0},{0,-1},{-1,0}}; int n = grid.length; PriorityQueue<Tmo> pq = new PriorityQueue<>(); pq.offer(new Tmo(0,0,grid[0][0])); int max = 0; int[][] exist = new int[n][n]; exist[0][0] = 1; while (!pq.isEmpty()){ Tmo poll = pq.poll(); int x = poll.x; int y = poll.y; int t = poll.value; max = Math.max(max,t); if (x == n-1 && y == n-1 ){ return max; } //朝着四个方向出发 选择短路径 如果结果是N,N则返回 for (int j = 0; j < forward.length ; j++) { //控制方向 int[] forw = forward[j]; int tx = x+forw[0]; int ty = y+forw[1]; if (tx <0 || tx >= n || ty <0 || ty >= n || exist[tx][ty] == 1 ){ continue; } exist[tx][ty] = 1; pq.offer(new Tmo(tx,ty,grid[tx][ty])); } } return -1; }
可以看到三种方式的提升还是比较明显