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.可以去看看。

posted @ 2019-08-18 19:42  于老师的父亲王老爷子  阅读(9)  评论(0编辑  收藏  举报