力扣刷題筆記:547. 省份數量(三種方法實現:深度優先搜尋、廣度優先搜尋、並查集;演算法搬運工、詳細解析、附完整題解程式碼)
題目:
547、省份數量
有 n 個城市,其中一些彼此相連,另一些沒有相連。如果城市 a 與城市 b 直接相連,且城市 b 與城市 c 直接相連,那麼城市 a 與城市 c 間接相連。
省份 是一組直接或間接相連的城市,組內不含其他沒有相連的城市。
給你一個 n x n 的矩陣 isConnected ,其中 isConnected[i][j] = 1 表示第 i 個城市和第 j 個城市直接相連,而 isConnected[i][j] = 0 表示二者不直接相連。
返回矩陣中 省份 的數量。
示例 1:
輸入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
輸出:2
示例 2:
輸入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
輸出:3
提示:
1 <= n <= 200
n == isConnected.length
n == isConnected[i].length
isConnected[i][j] 為 1 或 0
isConnected[i][i] == 1
isConnected[i][j] ==isConnected[j][i]
解題思路:
可以把 nn 個城市和它們之間的相連關係看成圖,城市是圖中的節點,相連關係是圖中的邊,給定的矩陣 isConnected 即為圖的鄰接矩陣,省份即為圖中的連通分量。
計算省份總數,等價於計算圖中的連通分量數,可以通過深度優先搜尋或廣度優先搜尋實現,也可以通過並查集實現。
方法一:深度優先搜尋
深度優先搜尋的思路是很直觀的。遍歷所有城市,對於每個城市,如果該城市尚未被訪問過,則從該城市開始深度優先搜尋,通過矩陣 \textit{isConnected}isConnected 得到與該城市直接相連的城市有哪些,這些城市和該城市屬於同一個連通分量,然後對這些城市繼續深度優先搜尋,直到同一個連通分量的所有城市都被訪問到,即可得到一個省份。遍歷完全部城市以後,即可得到連通分量的總數,即省份的總數。
實現程式碼(python):
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
def dfs(i: int):
for j in range(provinces):
if isConnected[i][j] == 1 and j not in visited:
visited.add(j)
dfs(j)
provinces = len(isConnected)
visited = set()
circles = 0
for i in range(provinces):
if i not in visited:
dfs(i)
circles += 1
return circles
方法二:廣度優先搜尋
也可以通過廣度優先搜尋的方法得到省份的總數。對於每個城市,如果該城市尚未被訪問過,則從該城市開始廣度優先搜尋,直到同一個連通分量中的所有城市都被訪問到,即可得到一個省份。
實現程式碼(python):
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
provinces = len(isConnected)
visited = set()
circles = 0
for i in range(provinces):
if i not in visited:
Q = collections.deque([i])
while Q:
j = Q.popleft()
visited.add(j)
for k in range(provinces):
if isConnected[j][k] == 1 and k not in visited:
Q.append(k)
circles += 1
return circles
方法三:並查集
計算連通分量數的另一個方法是使用並查集。初始時,每個城市都屬於不同的連通分量。遍歷矩陣 isConnected,如果兩個城市之間有相連關係,則它們屬於同一個連通分量,對它們進行合併。
遍歷矩陣 isConnected 的全部元素之後,計算連通分量的總數,即為省份的總數。
實現程式碼(python):
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
def find(index: int) -> int:
if parent[index] != index:
parent[index] = find(parent[index])
return parent[index]
def union(index1: int, index2: int):
parent[find(index1)] = find(index2)
provinces = len(isConnected)
parent = list(range(provinces))
for i in range(provinces):
for j in range(i + 1, provinces):
if isConnected[i][j] == 1:
union(i, j)
circles = sum(parent[i] == i for i in range(provinces))
return circles
作者:LeetCode-Solution
連結:https://leetcode-cn.com/problems/number-of-provinces/solution/sheng-fen-shu-liang-by-leetcode-solution-eyk0/ 來源:力扣(LeetCode)https://leetcode-cn.com/problems/number-of-provinces/