zoukankan      html  css  js  c++  java
  • [LeetCode] BFS解决的题目

    一.130  Surrounded Regions(https://leetcode.com/problems/surrounded-regions/description/)

    题目:

    解法:

    这道题的意思是将所有被X包围的O都变为X(边缘的不算),我们可以维护一个队列,先把四周的O的位置放进队列中,并把这个位置的值变为Y。然后每次从队列中拿出一个位置,把这个位置四周为O的位置的值变为Y,再把这个位置放进队列(为什么要先变值再进队列呢?在下一道题中会说)。一直到队列为空时,我们就成功地把所有直接或间接地与边缘的O相连的其他O变为了Y,剩余的O就是被X包围的了。然后遍历一遍,把为O的位置变为X,为Y的位置变为O,就得出结果了。 

    这道题利用到了BFS(宽度优先搜索)的思想,那么用深度优先是否可以呢?据说会TLE,因为图可能很大,递归会导致栈溢出。但是,我认为分别用这两种不同的方法思考一下这道题,可以锻炼利用bfs和dfs解题的思想。

    下面是代码:

    class Solution {
    public:
        void solve(vector<vector<char>>& board) {
            queue<int> x;
            queue<int> y;
            for (int i = 0; i < board.size(); i++) {
                for (int j = 0; j < board[i].size(); j++) {
                    if ((i == 0 || i == board.size() - 1 || 
                        j == 0 || j == board[i].size() - 1) &&
                        board[i][j] == 'O') {
                        x.push(i);
                        y.push(j);
                        board[i][j] = 'Y';
                    }
                }
            }
            while (!x.empty() && !y.empty()) {
                int i = x.front();
                int j = y.front();
                x.pop();
                y.pop();
                if (i - 1 >= 0 && board[i - 1][j] == 'O') {
                    x.push(i - 1);
                    y.push(j);
                    board[i - 1][j] = 'Y';
                } 
                if (i + 1 < board.size() && board[i + 1][j] == 'O') {
                    x.push(i + 1);
                    y.push(j);
                    board[i + 1][j] = 'Y';
                }
                if (j - 1 >= 0 && board[i][j - 1] == 'O') {
                    x.push(i);
                    y.push(j - 1);
                    board[i][j - 1] = 'Y';
                } 
                if (j + 1 < board[0].size() && board[i][j + 1] == 'O') {
                    x.push(i);
                    y.push(j + 1);
                    board[i][j + 1] = 'Y';
                }
            }
            for (int i = 0; i < board.size(); i++) {
                for (int j = 0; j < board[i].size(); j++) {
                    if (board[i][j] == 'Y') {
                        board[i][j] = 'O';
                    }
                    else {
                        board[i][j] = 'X';
                    }
                }
            }
        }
    };

    二. 200  Number of Islands(https://leetcode.com/problems/number-of-islands/description/)

    题目:

    解法:

    这道题的基本思想跟上面一道差不多,也是用bfs,维护一个队列:
    当遇到1的时候,把它改为0,进队列;(每次遇到新的island时)

    每次把一个位置出队列,并把这个位置四周为1的位置改为0,然后把这些位置放入队列中。当队列为空时,代表已经找到一个island的所有1了,结果+1。

    解法是简单的,但我做题的时候还是踩了不少坑:
    (1)我用了三层循环去写,因为我想着要判断什么时候所有位置都为0,但其实是多此一举,只需要遍历每一个位置就行了。

    (2)我一开始是先把位置放进队列,在出队列的时候才把这个位置的值变为0,但这是不对的:这样会造成一个位置的多次进队列(细想一下吧,出队列的时候才变为0,那在进队列到出队列的过程中这个位置的值还是1,还是会被其他位置检测到,多次加进队列),肯定会TLE。因此一定要先把值变为0,再加进队列。

    代码如下:

    class Solution {
    public:
        int numIslands(vector<vector<char> >& grid) {
            int ans = 0;
            queue<int> x, y;
            for (int i = 0; i < grid.size(); i++ ) {
                for (int j = 0; j < grid[0].size(); j++) {
                    if (grid[i][j] == '1') {
                        x.push(i);
                        y.push(j);
                        grid[i][j] = '0';
                        while (!x.empty() && !y.empty()) {
                            int i = x.front();
                            int j = y.front();
                            x.pop();
                            y.pop();
                            if (i - 1 >= 0 && grid[i - 1][j] == '1') {
                                x.push(i - 1);
                                y.push(j);
                                grid[i - 1][j] = '0';
                            }
                            if (i + 1 < grid.size() && grid[i + 1][j] == '1') {
                                x.push(i + 1);
                                y.push(j);
                                grid[i + 1][j] = '0';
                            }
                            if (j - 1 >= 0 && grid[i][j - 1] == '1') {
                                x.push(i);
                                y.push(j - 1);
                                grid[i][j - 1] = '0';
                            }
                            if (j + 1 < grid[0].size() && grid[i][j + 1] == '1') {
                                x.push(i);
                                y.push(j + 1);
                                grid[i][j + 1] = '0';
                            }
                        }   
                        ans++;
                    }
                }
            }
            return ans;
        }
    };

    或者:

    class Solution {
    public:
        int numIslands(vector<vector<char> >& grid) {
            int ans = 0;
            for (int i = 0; i < grid.size(); i++ ) {
                for (int j = 0; j < grid[0].size(); j++) {
                    if (grid[i][j] == '1') {
                        bfs(grid, i, j);
                        ans++;
                    }
                }
            }
            return ans;
        }
        void bfs(vector<vector<char> >& grid, int i, int j) {
            grid[i][j] = '0';
            if (i - 1 >= 0 && grid[i - 1][j] == '1') {
                bfs(grid, i - 1, j);    
            }
            if (i + 1 < grid.size() && grid[i + 1][j] == '1') {
                bfs(grid, i + 1, j);               
            }
            if (j - 1 >= 0 && grid[i][j - 1] == '1') {
                bfs(grid, i, j - 1);
            }
            if (j + 1 < grid[0].size() && grid[i][j + 1] == '1') {
                bfs(grid, i, j + 1);             
            }
        }
    };

     三.542 01 Matrix

     题目:

    解法:

    代码:

    class Solution {
    public:
        vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
            vector<vector<int> > ans = matrix;
            queue<int> x, y;
            for (int i = 0; i < ans.size(); i++) {
                for (int j = 0; j < ans[0].size(); j++) {
                    if (matrix[i][j] == 0) {
                        ans[i][j] = 0;
                        x.push(i);
                        y.push(j);
                    }
                    else {
                        ans[i][j] = -1;
                    } 
                }
            }
            while (!x.empty() && !y.empty()) {
                int i = x.front(), j = y.front();
                x.pop();
                y.pop();
                if (i - 1 >= 0 && ans[i - 1][j] == -1) {
                    ans[i - 1][j] = ans[i][j] + 1;
                    x.push(i - 1);
                    y.push(j);
                }
                if (i + 1 < ans.size() && ans[i + 1][j] == -1) {
                      ans[i + 1][j] = ans[i][j] + 1;
                      x.push(i + 1);
                    y.push(j);
                }
                if (j - 1 >= 0 && ans[i][j - 1] == -1) {
                    ans[i][j - 1] = ans[i][j] + 1;
                    x.push(i);
                    y.push(j - 1);
                }
                if (j + 1 < ans[0].size() && ans[i][j + 1] == -1) {
                    ans[i][j + 1] = ans[i][j] + 1;
                    x.push(i);
                    y.push(j + 1);
                }
            }
            return ans;
        }
    };

    2018.1.7补充:
    上面这一题,重做了一下,想到一个问题: 为什么可以不判断一下就直接ans[i][j] + 1呢?

    题目要求离最近的0的距离,而BFS是一层层叠加的、从小到大的,在if处加了ans[i + 1][j] == -1的判断,说明要已修改的值是不能再修改的,满足离最近的0的距离的要求。(描述得不是很清楚,不过自己能回想起就对了)

    LeetCode上面还有其他一些用BFS解决的问题,比如Word Ladder,但在前面已经写过了。

  • 相关阅读:
    【杭电】[4883]TIANKENG’s restaurant
    【杭电】[4883]TIANKENG’s restaurant
    【POJ】[1423]Big Number
    【POJ】[1423]Big Number
    【杭电】[1280]前m大的数
    【杭电】[1280]前m大的数
    【杭电】[1576]A/B
    【杭电】[1576]A/B
    [leetcode]346. Moving Average from Data Stream滑动窗口平均值
    [leetcode]99. Recover Binary Search Tree恢复二叉搜索树
  • 原文地址:https://www.cnblogs.com/fengziwei/p/7834529.html
Copyright © 2011-2022 走看看