「程式碼隨想錄演算法訓練營」第四十四天 | 圖論 part2

云雀AC了一整天發表於2024-08-22

200. 島嶼數量

題目連結:https://leetcode.cn/problems/number-of-islands/description/
文章講解:https://programmercarl.com/kamacoder/0099.島嶼的數量深搜.html
題目難度:中等
題目狀態:看題解

思路一:深搜版

方法 dfs

  • 引數: 接受一個字元網格 grid 和當前座標 (r, c)
  • 功能: 將當前島嶼的所有相連部分標記為已訪問。
  • 實現:
    • 改變當前座標的值為 '0',表示已訪問。
    • 檢查上下左右四個方向,如果相鄰位置是 '1',遞迴呼叫 dfs

方法 numIslands

  • 引數: 接受一個字元網格 grid
  • 功能: 計算網格中島嶼的數量。
  • 實現:
    • 獲取網格的行數 nr 和列數 nc
    • 初始化島嶼計數器 num_islands 為 0。
    • 遍歷網格中的每個元素,如果遇到 '1'
      • 增加島嶼計數器。
      • 呼叫 dfs 方法,從該位置開始將整個島嶼標記為已訪問。
    • 返回島嶼的總數。

程式碼一:

class Solution {
public:
    void dfs(vector<vector<char>> &grid, int r, int c) {
        int nr = grid.size();
        int nc = grid[0].size();
        grid[r][c] = '0';
        if(r - 1 >= 0 && grid[r - 1][c] == '1') dfs(grid, r - 1, c);
        if(r + 1 < nr && grid[r + 1][c] == '1') dfs(grid, r + 1, c);
        if(c - 1 >= 0 && grid[r][c - 1] == '1') dfs(grid, r, c - 1);
        if(c + 1 < nc && grid[r][c + 1] == '1') dfs(grid, r, c + 1);
    }

    int numIslands(vector<vector<char>>& grid) {
        int nr = grid.size();
        if(!nr) return 0;
        int nc = grid[0].size();
        
        int num_islands = 0;
        for(int r = 0; r < nr; ++r) {
            for(int c = 0; c < nc; ++c) {
                if(grid[r][c] == '1') {
                    ++num_islands;
                    dfs(grid, r, c);
                }
            }
        }
        return num_islands;
    }
};

消耗一:

image

思路二:廣搜版

思路在程式碼中。

程式碼二:

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int rowCount = grid.size();
        int colCount = grid[0].size();
        // 用來記錄島嶼數量
        int num_islands = 0;
        for (int row = 0; row < rowCount; row++) {
            for (int col = 0; col < colCount; col++) {
                // 如果當前點是島嶼的一部分
                if (grid[row][col] == '1') {
                    // 島嶼數量增加
                    num_islands++;
                    // 將當前位置標記為'0', 表示已訪問
                    grid[row][col] = '0';
                    // 建立一個佇列, 用於儲存島嶼的所有相鄰點
                    queue<pair<int, int>> neighbors; 
                    // 將當前位置加入佇列
                    neighbors.emplace(row, col);
                    // 當佇列不為空時,繼續搜尋
                    while (!neighbors.empty()) {
                        auto [row, col] = neighbors.front();
                        neighbors.pop();
                        // 檢查並將當前點的上下左右四個相鄰點加入佇列(如果它們是未訪問的島嶼部分)
                        if (row - 1 >= 0 && grid[row - 1][col] == '1') {
                            neighbors.emplace(row - 1, col);
                            grid[row - 1][col] = '0'; // 標記為已訪問
                        }
                        if (row + 1 < rowCount && grid[row + 1][col] == '1') {
                            neighbors.emplace(row + 1, col);
                            grid[row + 1][col] = '0'; // 標記為已訪問
                        }
                        if (col - 1 >= 0 && grid[row][col - 1] == '1') {
                            neighbors.emplace(row, col - 1);
                            grid[row][col - 1] = '0'; // 標記為已訪問
                        }
                        if (col + 1 < colCount && grid[row][col + 1] == '1') {
                            neighbors.emplace(row, col + 1);
                            grid[row][col + 1] = '0'; // 標記為已訪問
                        }
                    }
                }
            }
        }
        return num_islands;
    }
};

消耗二:

image

695. 島嶼的最大面積

題目連結:https://leetcode.cn/problems/max-area-of-island/description/
文章講解:https://programmercarl.com/kamacoder/0100.島嶼的最大面積.html
題目難度:中等
題目狀態:看題解

DFS解法

思路:

  • 方法 IslandDFS:這是一個遞迴方法,用於計算單個島嶼的面積。

    • 引數
      • grid:二維網格,表示地圖。
      • ij:當前格子的行和列索引。
    • 邏輯
      • 檢查當前索引是否在網格範圍內。
      • 如果當前格子是水(值為0),返回0。
      • 如果是陸地(值為1),將其標記為0(已訪問),然後遞迴地檢查四個方向(上、下、左、右)的相鄰格子。
      • 返回值為1(當前格子)加上所有相鄰陸地格子的面積。
  • 方法 maxAreaOfIsland:計算網格中所有島嶼的最大面積。

    • 邏輯
      • 初始化最大面積 ans 為0。
      • 遍歷網格的每個格子。
      • 對於每個陸地格子,呼叫 IslandDFS 計算該島嶼的面積,並更新最大面積。
      • 返回最大面積。

程式碼:

class Solution {
public:
    int IslandDFS(vector<vector<int>> &grid, int i, int j) {
        if((i < grid.size()) && (i >= 0) && (j < grid[0].size()) && (j >= 0)) {
            if(grid[i][j] == 0) return 0;
            else {
                grid[i][j] = 0;
                return 1 + IslandDFS(grid, i - 1, j) + IslandDFS(grid, i + 1, j) + IslandDFS(grid, i, j - 1) + IslandDFS(grid, i, j + 1);
            }
        } else 
            return 0;
    }

    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int ans = 0;
        for(int i = 0; i < grid.size(); ++i) {
            for(int j = 0; j < grid[0].size(); ++j) {
                ans = max({ans, IslandDFS(grid, i, j)});
            }
        }
        return ans;
    }
};

消耗:

image

BFS解法

看不懂。。。

程式碼:

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int ans = 0;
        for (int i = 0; i != grid.size(); ++i) {
            for (int j = 0; j != grid[0].size(); ++j) {
                int cur = 0;
                queue<int> queuei;
                queue<int> queuej;
                queuei.push(i);
                queuej.push(j);
                while (!queuei.empty()) {
                    int cur_i = queuei.front(), cur_j = queuej.front();
                    queuei.pop();
                    queuej.pop();
                    if (cur_i < 0 || cur_j < 0 || cur_i == grid.size() || cur_j == grid[0].size() || grid[cur_i][cur_j] != 1) {
                        continue;
                    }
                    ++cur;
                    grid[cur_i][cur_j] = 0;
                    int di[4] = {0, 0, 1, -1};
                    int dj[4] = {1, -1, 0, 0};
                    for (int index = 0; index != 4; ++index) {
                        int next_i = cur_i + di[index], next_j = cur_j + dj[index];
                        queuei.push(next_i);
                        queuej.push(next_j);
                    }
                }
                ans = max(ans, cur);
            }
        }
        return ans;
    }
};

相關文章