[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,但在前面已經寫過了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM