LeetCode:1162. As Far from Land as Possible
应该很明显是一个使用bfs的题目,而且应该是一个常规题目,但是思维没转换过来。
首先是一个没用bfs的解法,是自己想出来的,时间很长:
class Solution {
public:
int maxDistance(vector<vector<int>>& grid) {
int rows = grid.size();
int cols = grid[0].size();
bool landExist = false;
bool waterExist = false;
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j) {
if (grid[i][j] == 0)
waterExist = true;
else
landExist = true;
if (landExist && waterExist)
break;
}
if (!(landExist && waterExist))
return -1;
int maxDist = 0;
vector<pair<int, int>> waters, lands;
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j) {
if (grid[i][j] == 0)
waters.push_back(make_pair(i, j));
else
lands.push_back(make_pair(i, j));
}
for (auto water : waters) {
int dist = INT_MAX;
for (auto land : lands) {
int tempDist = abs(water.first - land.first) + abs(water.second - land.second);
dist = min(dist, tempDist);//这个必须在这儿,不能在下面的if后面,否则dist可能存的是上一轮的最小值,导致影响到maxDist
if (tempDist < maxDist) {
break;
}
}
maxDist = max(maxDist, dist);
}
return maxDist;
}
};
然后是一个bfs的解法,从评论区看来的:
class Solution {
public:
int maxDistance(vector<vector<int>>& grid) {
int N = grid.size();
queue<pair<int, int>> q;//里面存的是当前这一层将要扩散的位置
vector<vector<bool>> visited(N, vector<bool>(N, false));
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j) {
if (grid[i][j] == 1) {
q.push(make_pair(i, j));
visited[i][j] = true;
}
}
int level = -1;
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
while (!q.empty()) {
++level;
int sz = q.size();
while (sz-- > 0) {
auto p = q.front();
q.pop();
int x = p.first;
int y = p.second;
for (int i = 0; i < 4; ++i) {
int newX = x + dir[i][0];
int newY = y + dir[i][1];
if (newX >= 0 && newX < N && newY >= 0 && newY < N && !visited[newX][newY]) {
visited[newX][newY] = true;
q.push(make_pair(newX, newY));
}
}
}
}
return level <= 0? -1 : level;
}
};
//这个bfs给我启示很多,自己也想过bfs,但是都是从水的角度bfs,这样坏处是每个水都要做一次bfs,消耗太大了。
//而从陆地的角度来bfs的话,只需要将需要扩散的位置都存进queue里面,每次都向外扩散就行了,这样是做一个总体的bfs,不需要每个陆地都bfs。每次扩散一次,每个待扩散的地方都要扩散。
//每块水第一次被访问时level为多少,就是它距离最近的陆地是多少。简直了!!!
//每个水的地方只要有被访问过,就不需要再次访问了。
应该是一个很简单,直观的题,但是竟然没有想到,之后注意这种思路吧。
补充相似思路的bfs的一道题目:310.可以去看看。