Leetcode 200. 島嶼的個數(擴充套件)
阿新 • • 發佈:2018-11-15
1.題目描述
給定一個由 '1'
(陸地)和 '0'
(水)組成的的二維網格,計算島嶼的數量。一個島被水包圍,並且它是通過水平方向或垂直方向上相鄰的陸地連線而成的。你可以假設網格的四個邊均被水包圍。
示例 1:
輸入: 11110 11010 11000 00000 輸出: 1
示例 2:
輸入: 11000 11000 00100 00011 輸出: 3
2.解題思路
演算法核心框架:深度搜索+遞迴
- 深度搜索:整個島嶼是一個“二維矩陣”(vector<vectro<char>>),使用深度優先搜尋遍歷一遍整個矩陣;
- 遞迴:當掃描到'1'時,呼叫infect()函式,將該 ‘1’ 上下左右相鄰的位置都感染為 ‘2’,遞迴呼叫infect()的結果是從起始的 ‘1’ 開始而相連的一片‘1’都被感染為 ‘2’;
3.提交程式碼
class Solution { public: int numIslands(vector<vector<char>>& grid) { //行空 或 列空 if(grid.empty() || grid[0].empty()){ return 0; }int N = grid.size();//grid網格的列長 int M = grid[0].size();//grid網格的行長 int res = 0; //深度優先搜尋 for(int i = 0; i < N; ++i){ for(int j = 0; j < M; ++j){ if(grid[i][j] == '1'){ ++res;//只計數作為起始感染點的1的個數,即為島嶼個數 infect(grid,i,j,N,M); } } }return res; } void infect(vector<vector<char>>& grid,int i,int j,int N,int M){ if(i<0 || i>=N || j<0 || j>= M || grid[i][j] != '1'){ return; } grid[i][j] = '2'; infect(grid,i+1,j,N,M); infect(grid,i-1,j,N,M); infect(grid,i,j-1,N,M); infect(grid,i,j+1,N,M); } };
4.擴充套件解法——並查集
假設題目給的資料非常多,也就是所要查詢的矩陣相當大,這種情況下,我們該怎麼辦?很明顯,上面的解法只能在單機上執行,效率有上限。
因此,我們需要採用多工處理的“平行計算”的思路,將大的原始矩陣分割成多個小的矩陣,分佈在多臺機器上進行計算,最後合併每臺機器的島嶼數量,並去重,得到最終的島嶼總數。
#問題的難點:邊界資訊該如何合併?
01111 | 11110 11000 | 00000 11000 | 00000 01111 | 11110 島數1 島數2 合併結果:島數1 (怎麼得到?)
#解決思路:需要儲存的關鍵資訊有兩個:
- (1)每個分矩陣的島嶼個數;
- (2)記錄邊界點的感染中心——需要使用到並查集的結構,快速查詢兩個‘1’是否屬於同一個集合(相同的感染中心)。
#並查集知識點