生活随笔
收集整理的這篇文章主要介紹了
LeetCode 305. 岛屿数量 II(并查集)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
1. 題目
假設你設計一個游戲,用一個 m 行 n 列的 2D 網格來存儲你的游戲地圖。
起始的時候,每個格子的地形都被默認標記為「水」。
我們可以通過使用 addLand 進行操作,將位置 (row, col) 的「水」變成「陸地」。
你將會被給定一個列表,來記錄所有需要被操作的位置,然后你需要返回計算出來 每次 addLand 操作后島嶼的數量。
注意:一個島的定義是被「水」包圍的「陸地」,通過水平方向或者垂直方向上相鄰的陸地連接而成。
你可以假設地圖網格的四邊均被無邊無際的「水」所包圍。
請仔細閱讀下方示例與解析,更加深入了解島嶼的判定。
示例
:
輸入
: m
= 3, n
= 3, positions
= [[0,0], [0,1], [1,2], [2,1]]
輸出
: [1,1,2,3]
解析
:
起初,二維網格 grid 被全部注入「水」。(
0 代表「水」,
1 代表「陸地」)
0 0 0
0 0 0
0 0 0操作 #
1:
addLand(0, 0) 將 grid
[0][0] 的水變為陸地。
1 0 0
0 0 0 Number of islands
= 1
0 0 0操作 #
2:
addLand(0, 1) 將 grid
[0][1] 的水變為陸地。
1 1 0
0 0 0 島嶼的數量為
1
0 0 0操作 #
3:
addLand(1, 2) 將 grid
[1][2] 的水變為陸地。
1 1 0
0 0 1 島嶼的數量為
2
0 0 0操作 #
4:
addLand(2, 1) 將 grid
[2][1] 的水變為陸地。
1 1 0
0 0 1 島嶼的數量為
3
0 1 0拓展:
你是否能在
O(k log mn
) 的時間復雜度程度內完成每次的計算?
(k 表示 positions 的長度)
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/number-of-islands-ii
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
2. 解題
參考數據結構:并查集(Disjoint-Set)
2.1 超時解
125 / 162 個通過測試用例
- 將矩陣的每個位置看成并查集中的一個點,每次加入一個島嶼,把四周是1的點合并掉
- 計算集團個數
- 時間復雜度 O(kmn)O(kmn)O(kmn)
class dsu
{
public:vector
<int> f
;dsu(int n
){f
.resize(n
);for(int i
= 0; i
< n
; ++i
)f
[i
] = i
;}void merge(int a
, int b
){int fa
= find(a
);int fb
= find(b
);f
[fa
] = fb
;}int find(int a
){int origin
= a
;while(a
!= f
[a
])a
= f
[a
];return f
[origin
] = a
;}int countUni(vector
<vector
<int>> &grid
){int count
= 0, x
, y
, n
= grid
[0].size();for(int i
= 0; i
< f
.size(); ++i
){ x
= i
/n
, y
= i
-x
*n
;if(i
== find(i
) && grid
[x
][y
]==1)count
++;}return count
;}
};
class Solution {
public:vector
<int> numIslands2(int m
, int n
, vector
<vector
<int>>& positions
) {int N
= m
*n
, pos
, x
, y
;vector
<vector
<int>> grid(m
,vector
<int>(n
,0));dsu
u(N
);vector
<int> ans(positions
.size());vector
<vector
<int>> dir
= {{1,0},{0,1},{0,-1},{-1,0}};for(int i
= 0, k
; i
< positions
.size(); ++i
){grid
[positions
[i
][0]][positions
[i
][1]] = 1;pos
= positions
[i
][0]*n
+positions
[i
][1];for(k
= 0; k
< 4; ++k
){x
= positions
[i
][0] + dir
[k
][0];y
= positions
[i
][1] + dir
[k
][1];if(x
>=0 && x
<m
&& y
>=0 && y
<n
&& grid
[x
][y
]==1)u
.merge(pos
, x
*n
+y
);}ans
[i
] = u
.countUni(grid
);}return ans
;}
};
2.1 改進計算方法
- 并查集merge 函數返回是否被合并了,合并了數量就減1
- 注意有重復島嶼,不能算
class dsu
{
public:vector
<int> f
;dsu(int n
){f
.resize(n
);for(int i
= 0; i
< n
; ++i
)f
[i
] = i
;}bool merge(int a
, int b
){int fa
= find(a
);int fb
= find(b
);if(fa
!= fb
){f
[fa
] = fb
;return true;}return false;}int find(int a
){int origin
= a
;while(a
!= f
[a
])a
= f
[a
];return f
[origin
] = a
;}
};
class Solution {
public:vector
<int> numIslands2(int m
, int n
, vector
<vector
<int>>& positions
) {int N
= m
*n
, pos
, x
, y
;vector
<vector
<int>> grid(m
,vector
<int>(n
,0));dsu
u(N
);vector
<int> ans(positions
.size());vector
<vector
<int>> dir
= {{1,0},{0,1},{0,-1},{-1,0}};unordered_set
<int> s
;for(int i
= 0, k
; i
< positions
.size(); ++i
){ans
[i
] = (i
>0 ? ans
[i
-1] : 0 )+1;grid
[positions
[i
][0]][positions
[i
][1]] = 1;pos
= positions
[i
][0]*n
+positions
[i
][1];if(s
.count(pos
)){ans
[i
]--;continue;}s
.insert(pos
);for(k
= 0; k
< 4; ++k
){x
= positions
[i
][0] + dir
[k
][0];y
= positions
[i
][1] + dir
[k
][1];if(x
>=0 && x
<m
&& y
>=0 && y
<n
&& grid
[x
][y
]==1){if(u
.merge(pos
, x
*n
+y
))ans
[i
]--;}}}return ans
;}
};
156 ms 34.7 MB
我的CSDN博客地址 https://michael.blog.csdn.net/
長按或掃碼關注我的公眾號(Michael阿明),一起加油、一起學習進步!
總結
以上是生活随笔為你收集整理的LeetCode 305. 岛屿数量 II(并查集)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。