题目地址:
https://leetcode.com/problems/map-of-highest-peak/
给定一个
m
×
n
m\times n
m×n的
0
−
1
0-1
0−1矩阵
A
A
A,要求构造一个新的矩阵
C
C
C满足如下要求:
1、
C
C
C的所有元素都非负;
2、若
A
[
i
]
[
j
]
=
1
A[i][j]=1
A[i][j]=1则
C
[
i
]
[
j
]
=
0
C[i][j]=0
C[i][j]=0;
3、对于
C
C
C中相邻的元素,它们的差的绝对值最多是
1
1
1。这里的相邻指的是四相邻。
同时要求
C
C
C的最大值最大,求
C
C
C。
其实只需要从 C [ i ] [ j ] = 0 C[i][j]=0 C[i][j]=0的位置做BFS即可,第一次接触的位置为它的前驱的数加 1 1 1。我们稍微说明一下正确性。首先如果某两个相邻格子元素之差大于 1 1 1了,比如 C [ x 1 ] [ y 1 ] > C [ x 2 ] [ y 2 ] + 1 C[x_1][y_1]> C[x_2][y_2]+1 C[x1][y1]>C[x2][y2]+1那么说明 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)这个位置应该由 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)这个位置扩展而来(因为 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)入队之后下一层BFS就会拓展到 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)),这就矛盾了,因为我们不允许同一个位置被BFS到两次。至于最大值最大这一点,可以反证法,如果某个位置的能达到更大值,那么考虑BFS树从树根走到这个位置的路径(可以想象树根是个虚拟节点),这个路径必然存在相邻两个位置差大于 1 1 1,矛盾。代码如下:
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
public int[][] highestPeak(int[][] A) {
int m = A.length, n = A[0].length;
Queue<int[]> queue = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (A[i][j] == 1) {
A[i][j] = 0;
queue.offer(new int[]{i, j});
} else {
A[i][j] = -1;
}
}
}
int[] d = {1, 0, -1, 0, 1};
for (int h = 1; !queue.isEmpty(); h++) {
for (int i = queue.size() - 1; i >= 0; i--) {
int[] cur = queue.poll();
int x = cur[0], y = cur[1];
for (int k = 0; k < 4; k++) {
int nextX = x + d[k], nextY = y + d[k + 1];
if (0 <= nextX && nextX < m && 0 <= nextY && nextY < n && A[nextX][nextY] == -1) {
A[nextX][nextY] = h;
queue.offer(new int[]{nextX, nextY});
}
}
}
}
return A;
}
}
时空复杂度 O ( m n ) O(mn) O(mn)。