1. 程式人生 > >leetcode圖論連通域題目集合

leetcode圖論連通域題目集合

島嶼的個數leetcode 200

題目:

給定一個由 '1'(陸地)和 '0'(水)組成的的二維網格,計算島嶼的數量。
一個島被水包圍,並且它是通過水平方向或垂直方向上相鄰的陸地連線而成的。
你可以假設網格的四個邊均被水包圍。

示例 1:

輸入:
11110
11010
11000
00000

輸出: 1

示例 2:

輸入:
11000
11000
00100
00011

輸出: 3


這裡其實就是求出最大連通域個數,分別用BFSDFS求解:
解法一:bfs

//bfs
class Solution {
public:
    int numIslands(vector<vector<char> >& grid) {
        if(grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size(), res = 0;
        
        for(int i = 0; i<m;++i)
        {
            for(int j = 0; j<n; j++)
            {
                if(grid[i][j] == '1')
                {
                    
                    bfs(i, j, grid);
                    res++;
                }
            }
        }
        return res;
    }
    
 
     void bfs(int x, int y, vector<vector<char> >& grid) {
            if (x < 0 || y < 0 || x >= grid.size() || y >= grid[0].size() || grid[x][y] == '0') return;
            grid[x][y] = '0';
            bfs(x + 1, y, grid);
            bfs(x - 1, y, grid);
            bfs(x, y + 1, grid);
            bfs(x, y - 1, grid);
        }
    

};

解法二:dfs

class Solution {
public:
    int numIslands(vector<vector<char> >& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size(), res = 0;
        vector<vector<bool> > visited(m, vector<bool>(n, false));
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == '1' && !visited[i][j]) {
                    numIslandsDFS(grid, visited, i, j);
                    ++res;
                }
            }
        }
        return res;
    }
    void numIslandsDFS(vector<vector<char> > &grid, vector<vector<bool> > &visited, int x, int y) {
        if (x < 0 || x >= grid.size()) return;
        if (y < 0 || y >= grid[0].size()) return;
        if (grid[x][y] != '1' || visited[x][y]) return;
        visited[x][y] = true;
        numIslandsDFS(grid, visited, x - 1, y);
        numIslandsDFS(grid, visited, x + 1, y);
        numIslandsDFS(grid, visited, x, y - 1);
        numIslandsDFS(grid, visited, x, y + 1);
    }
};

島嶼的周長 leetcode463

題目

給定一個包含 0 和 1 的二維網格地圖,其中 1 表示陸地 0 表示水域。
網格中的格子水平和垂直方向相連(對角線方向不相連)。
整個網格被水完全包圍,但其中恰好有一個島嶼
(或者說,一個或多個表示陸地的格子相連組成的島嶼)。
島嶼中沒有“湖”(“湖” 指水域在島嶼內部且不和島嶼周圍的水相連)。
格子是邊長為 1 的正方形。網格為長方形,且寬度和高度均不超過 100 。
計算這個島嶼的周長。

在這裡插入圖片描述

這道題給了我們一個格子圖,若干連在一起的格子形成了一個小島,規定了圖中只有一個相連的島,且島中沒有湖,讓我們求島的周長。我們知道一個格子有四條邊,但是當兩個格子相鄰,周圍為6,若某個格子四周都有格子,那麼這個格子一條邊都不算在周長裡。那麼我們怎麼統計出島的周長呢?第一種方法,我們對於每個格子的四條邊分別來處理,首先看左邊的邊,只有當左邊的邊處於第一個位置或者當前格子的左面沒有島格子的時候,左邊的邊計入周長。其他三條邊的分析情況都跟左邊的邊相似,這裡就不多敘述了,參見程式碼。

解法一:

class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size(), res = 0;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 0) continue;
                if (j == 0 || grid[i][j - 1] == 0) ++res;
                if (i == 0 || grid[i - 1][j] == 0) ++res;
                if (j == n - 1 || grid[i][j + 1] == 0) ++res;
                if (i == m - 1 || grid[i + 1][j] == 0) ++res;
            }
        }
        return res;
    }
};

下面這種方法對於每個島嶼格子先預設加上四條邊,然後檢查其左面和上面是否有島嶼格子,有的話分別減去兩條邊,這樣也能得到正確的結果,參見程式碼。

解法二:

class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        int res = 0, m = grid.size(), n = grid[0].size();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 0) continue;
                res += 4;
                if (i > 0 && grid[i - 1][j] == 1) res -= 2;
                if (j > 0 && grid[i][j - 1] == 1) res -= 2;
            }
        }
        return res;
    }
};