题目

类型:BFS
image.png
image.png

解题思路

「单源最短路」问题:本质是在一个边权为 的图上,求从特定「源点」出发到达特定「汇点」的最短路径。
与「单源最短路」不同,「多源最短路」问题是求从「多个源点」到达「一个/多个汇点」的最短路径。通过建立「虚拟源点」的方式,我们可以「多源 BFS」转换回「单源 BFS」问题。

题目规定了水域区域的高度为 0,然后相邻格子之间的高度差至多为 1,可以将所有水域(高度为 0)区域进行入队,然后跑一遍 BFS 即可。
将所有水域(高度为 0)区域进行入队的操作可看作是将与「虚拟源点」链接的节点进行入队(也等价于起始只将虚拟源点入队):
image.png

对于一个「陆地」区域(高度可变)而言,其所能填入的高度,取决于其距离其他「水域」区域的距离,而我们最终要让整个答案矩阵合法,因此每个「陆地」区域应该取其所能填入的高度的「下界」,即只由「距离它最近的水域」区域所更新,这符合 BFS 的性质

代码

  1. class Solution {
  2. public int[][] highestPeak(int[][] g) {
  3. int m = g.length, n = g[0].length;
  4. int[][] ans = new int[m][n];
  5. Deque<int[]> d = new ArrayDeque<>();
  6. for (int i = 0; i < m; i++) {
  7. for (int j = 0; j < n; j++) {
  8. if (g[i][j] == 1) d.addLast(new int[]{i, j});
  9. ans[i][j] = g[i][j] == 1 ? 0 : -1;
  10. }
  11. }
  12. int[][] dirs = new int[][]{{1,0}, {-1,0}, {0,1}, {0,-1}};
  13. int h = 1;
  14. while (!d.isEmpty()) {
  15. int size = d.size();
  16. while (size-- > 0) {
  17. int[] info = d.pollFirst();
  18. int x = info[0], y = info[1];
  19. for (int[] di : dirs) {
  20. int nx = x + di[0], ny = y + di[1];
  21. if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
  22. if (ans[nx][ny] != -1) continue;
  23. ans[nx][ny] = h;
  24. d.addLast(new int[]{nx, ny});
  25. }
  26. }
  27. h++;
  28. }
  29. return ans;
  30. }
  31. }