topic
https://www.lintcode.com/problem/1911
你现在手里有一份大小为 N x N 的网格grid,上面的每个单元格都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。
如果网格上只有陆地或者海洋,请返回 -1。
1 <= grid.length == grid[0].length <= 100
grid[i][j] 不是 0 就是 1
样例
样例 1:
输入:
[[1,0,1],[0,0,0],[1,0,1]]
输出:
2
解释:
海洋单元格 (1, 1) 和所有陆地单元格之间的距离都达到最大,最大距离为 2。
样例 2:
输入:
[[1,0,0],[0,0,0],[0,0,0]]
输出:
4
解释:
海洋单元格 (2, 2) 和所有陆地单元格之间的距离都达到最大,最大距离为 4。
Ideas
解法:多起点bfs
算法 / 数据结构:BFS
解题思路
一开始的时候就把小岛加入队列,标记加入队列的小岛,一轮一轮扩展,
进行Bfs遍历,队列中最后一个被找到的位置,就是所求的答案。
复杂度分析
时间复杂度:O(n^2)
该算法考虑最坏情况下,所有的区域都是海洋,那么每一个区域都会进行 BFS。程序的总的时间复杂度是 O(n^2)。
空间复杂度:O(n^2)
二位数组的大小是n^2
code
public class Solution {
/**
* @param grid: An array.
* @return: An integer.
*/
public int maxDistance(int[][] grid) {
/*
解法:多起点bfs
算法 / 数据结构:BFS
解题思路
一开始的时候就把小岛加入队列,标记加入队列的小岛,一轮一轮扩展,
进行Bfs遍历,队列中最后一个被找到的位置,就是所求的答案。
复杂度分析
时间复杂度:O(n^2)
该算法考虑最坏情况下,所有的区域都是海洋,那么每一个区域都会进行 BFS。程序的总的时间复杂度是 O(n^2)。
空间复杂度:O(n^2)
二位数组的大小是n^2
*/
int[][] dirx = {
{
-1,0},{
1,0},{
0,-1},{
0,1}};
Queue<int[]> q = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
int n = grid.length,m= grid[0].length;
for (int i = 0; i <n ; i++) {
for (int j = 0; j <m ; j++) {
if(grid[i][j] ==1){
q.add(new int[]{
i,j});
visited.add(i*m+j);
}
}
}
if(q.size() == n*m || q.size() ==0) return -1; //全是陆地或者海洋
int step = 0;
while (!q.isEmpty()){
step++;
int qlen = q.size();
for (int k = 0; k <qlen ; k++) {
int[] arr = q.poll();
int x = arr[0],y=arr[1];
for (int[] dir : dirx) {
int x1 = x+dir[0],y1=y+dir[1];
if(x1 >=0 && x1<n && y1>=0 && y1< m && grid[x1][y1] ==0){
if(visited.contains(x1*m+y1))
continue;
q.add(new int[]{
x1,y1});
visited.add(x1*m+y1);
}
}
}
}
return step ==0 ? -1:step-1;
}
}