問題描述:
給你一個由 '1'(陸地)和 '0'(水)組成的的二維網格,請你計算網格中島嶼的數量。島嶼總是被水包圍,並且每座島嶼只能由水平方向或豎直方向上相鄰的陸地連接形成。此外,你可以假設該網格的四條邊均被水包圍。
對於網格類遍歷問題,深度優先搜索dfs是一種典型的解決方案,類比於二叉樹的DFS,其程序框架如下:
void dfs(TreeNode* node){
if(node == NULL)
return;
dfs(node->left);
dfs(node->right);
}
程序的思想是:(1)先判斷一下當前結點是否爲空,即判斷當前探索位置的有效性,(2)如果通過有效性判斷,則遞歸遍歷當前結點的孩子結點,或稱連通結點,進行結點探索。
二叉樹可以看作是一種簡單的無環的圖結構,對於網格問題,其實是一種複雜的圖結構,其dfs遍歷的思想框架與二叉樹其實是一致的,dfs流程同樣是先判斷,在遞歸遍歷:
(1)判斷條件:當前位置是否越界(網格通常是有邊界限制的);判斷當前結點是否滿足題目限制(如陸地爲1)
(2)遞歸遍歷:通常遍歷當前位置的“ 上、下、左、右” 四個位置。
class Solution {
public:
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;
}
private:
void dfs(vector<vector<char>>& grid, int r, int c) {
if (!inArea(grid, r, c))
return;
if(grid[r][c]!='1')
return;
grid[r][c] = '0';
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
}
bool inArea(vector<vector<char>>& grid, int r, int c) {
return 0 <= r && r < grid.size() && 0 <= c && c < grid[0].size();
}
};