一、題目介紹
今天要練習的題目是LeetCode 200:Number of Islands
題目會給我們一個由1和0組成的二維grid
1代表陸地0代表水1透過上下左右相鄰,就屬於同一座島嶼grid中總共有幾座島嶼例如:
grid =
[
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
這個例子中所有相連的1都屬於同一座島,所以答案是:1
另一個例子:
grid =
[
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
可以找到三個互相沒有連接的區域,因此答案是:3
二、解題思路
這題可以使用DFS(深度優先搜尋)或BFS(廣度優先搜尋)
我們可以從左上角開始逐格檢查
如果遇到0
→ 跳過
如果遇到1
→ 找到一座新的島嶼
→ islandCount + 1
→ 將這座島嶼所有相連的陸地找出來
這裡最重要的一點是:同一座島只能計算一次
例如:
1 1
1 1
雖然有四個1,但它們全部相連,所以只能算1座島
因此找到一個1後,就要把與它連通的所有1都標記成「已經搜尋過」
三、使用DFS搜尋島嶼
假設我們在這個位置找到1
0 0 0
0 1 0
0 0 0
就從這個位置開始往四個方向搜尋
只要遇到相鄰的1,就繼續DFS
為了避免重複搜尋,可以把拜訪過的1改成0
例如:
1 1 0
1 1 0
0 0 0
搜尋完成後變成
0 0 0
0 0 0
0 0 0
這樣之後掃描到這些位置時,就不會再次計算同一座島嶼
四、Java實作DFS

五、Python實作DFS

七、BFS解法
除了DFS,也可以使用BFS
DFS使用遞迴一路深入
起點
↓
往下一個陸地
↓
繼續搜尋
↓
直到不能走
BFS則是利用Queue
起點
↓
第一層相鄰陸地
↓
第二層相鄰陸地
↓
繼續向外擴散
Java BFS


八、Java與Python解法比較
九、時間與空間複雜度
假設grid的大小為m × n
時間複雜度:O(m × n)
空間複雜度:O(m × n)
十、Day 21 Flood Fill 與 Day 22 Number of Islands 比較
兩題最大的共同點就是:Grid上的連通區域搜尋。
Day 21 是「找到一個區域並修改它」,Day 22 則是「找到一個區域並計數」
十一、實作結果
Leetcode測試結果:Accepted
十二、今日學習心得
今天的Number of Islands延續了昨天Flood Fill的概念,讓我更加理解DFS與BFS在二維Grid中的應用方式。這題最重要的地方,是找到一個1時不能只把它當成一個陸地計算,而是要繼續搜尋與它上下左右相連的所有陸地,將整個連通區域視為同一座島。
在實作過程中,我也了解到「標記已拜訪的位置」是Grid搜尋中非常重要的技巧。這次直接將1 修改成0,就可以避免同一座島被重複計算,也不需要額外建立visited陣列。
和 Day 21 的 Flood Fill 比較後,我發現兩題雖然題目看起來不同,但背後使用的搜尋概念非常接近。Flood Fill 是找到連通區域後修改顏色,而 Number of Islands 是找到連通區域後進行計數。這讓我開始了解到,學習演算法時不一定要只記住單一題目的解法,更重要的是找出不同問題背後共通的解題模式。
今天也再次練習了 DFS 與 BFS,讓我對 Grid、連通區域以及四方向搜尋有更完整的理解。這些概念未來也可以應用在迷宮、地圖、影像處理等問題上。