給定乙個由'1'
(陸地)和'0'
(水)組成的的二維網格,計算島嶼的數量。乙個島被水包圍,並且它是通過水平方向或垂直方向上相鄰的陸地連線而成的。你可以假設網格的四個邊均被水包圍。
示例 1:
輸入:
11110
11010
11000
00000
輸出: 1
示例 2:
輸入:
11000
11000
00100
00011
輸出: 3
演算法核心框架:深度搜尋+遞迴
class solution
int n = grid.size();//grid網格的列長
int m = grid[0].size();//grid網格的行長
int res = 0;
//深度優先搜尋
for(int i = 0; i < n; ++i)}}
return res;
}void infect(vector>& grid,int i,int j,int n,int m)
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);
}};
並查集的結構本質是多叉樹,是樹的一種應用。對於並查集的具體結構,不同的教材版本有不同的定義,我這裡介紹的文末所列參考資料中定義。
初始時:每個元素的父指標指向自己
1->1 2->2 3->3 4->4 5->5
合併1,2,得到set1: 2的父指標指向1
2——>1->1
合併3,4,5,得到set2: 集合相等,可以任意選擇哪個集合合併到哪個集合,這裡3和4併入5
3——>5->5
4——>5->5
合併set1和set2:小集合set1的代表結點的父指標指向set2的代表結點
2——>1——>5->5
3——>5->5
4——>5->5
查詢元素2和4是否在同乙個集合:
2往上查詢得到代表結點為5,4往上查詢得到代表結點為5,所以,2和4在同乙個集合中。
並查集是一種簡單的集合表示,主要的作用有兩個:
快速的,檢查兩個元素是否屬於同乙個集合,issameset(a,b);
快速的,將兩個元素各自所在的不同集合合併在一起,union(a,b),指的合併a所在的集合set1和b所在的集合set2;
另外,特別注意一點:並查集要求一次性獲得所有的處理資料樣本,不支援處理動態的資料流。
假設題目給的資料非常多,也就是所要查詢的矩陣相當大,這種情況下,我們該怎麼辦?很明顯,上面的解法只能在單機上執行,效率有上限。
因此,我們需要採用多工處理的「平行計算」的思路(讓你在面試官面前脫穎而出),將大的原始矩陣分割成多個小的矩陣,分布在多台機器上進行計算,最後合併每台機器的島嶼數量,並去重,得到最終的島嶼總數。
#問題的難點:邊界資訊該如何合併?
01111 | 11110
11000 | 00000
11000 | 00000
01111 | 11110
島數1 島數2
合併結果:島數1 (怎麼得到?)
(1)每個分矩陣的島嶼個數;#解決思路:需要儲存的關鍵資訊有兩個:
(2)記錄邊界點的感染中心——需要使用到並查集的結構,快速查詢兩個『1』是否屬於同乙個集合(相同的感染中心)。
舉例:劃分為2個矩陣
矩陣1 矩陣2
01111 | 11110
01111 | 10000
00000 | 10001
01111 | 10001
00001 | 00111
(1)矩陣1的島嶼個數為2,矩陣2的島嶼個數為2
(2)邊界點的感染中心:為了易於區別不同的'1',設紅、藍、黑、綠色島嶼的感染中心(感染起始點的那個'1')的分別為a、b、c、d
0a111 | b1110
01111 | 10000
00000 | 1000d
0c111 | 10001
00001 | 00111
第1行邊界的兩個1,感染中心分別為a和b,不相同,島嶼數減一,並且將感染中心為b的島嶼上的1的感染中心全部置為a;
第2行邊界的兩個1,感染中心分別為a和a(島嶼b的感染中心在上一步更新為a了),相同,跳過;
第3行邊界的兩個不全為1,跳過;
第4行邊界的兩個1,感染中心分別為c和a,不相同,島嶼數減一,並且將感染中心為c的島嶼上的1的感染中心全部置為a;
第5行邊界的兩個不全為1,跳過;
島嶼總數:2+2 -1 -1 = 2
兩個分矩陣的合併處理解決了,四個或八個矩陣的合併同理,只是需要重複的步驟多了。 島嶼的個數
給乙個01矩陣,求不同的島嶼的個數。0代表海,1代表島,如果兩個1相鄰,那麼這兩個1屬於同乙個島。我們只考慮上下左右為相鄰。樣例 在矩陣 1,1,0,0,0 0,1,0,0,1 0,0,0,1,1 0,0,0,0,0 0,0,0,0,1 中有3個島.借鑑網上 整理得 public class sol...
433 島嶼的個數
4.11 陣列統一賦值的函式arrays.fill 感覺自己的想法很野啊,用總的點的個數去減。就是要注意邊界值,陣列是從下標0開始的,一定要注意。public class solution 行數 int m grid 0 length if m 0 列數 int count m n boolean ...
島嶼的個數 LintCode
給乙個01矩陣,求不同的島嶼的個數。0代表海,1代表島,如果兩個1相鄰,那麼這兩個1屬於同乙個島。我們只考慮上下左右為相鄰。樣例 在矩陣 1,1,0,0,0 0,1,0,0,1 0,0,0,1,1 0,0,0,0,0 0,0,0,0,1 中有 3 個島.思路 利用遞迴,將與當前島嶼相接壤的島存入ma...