1. 程式人生 > 其它 >力扣刷題筆記:547. 省份數量(三種方法實現:深度優先搜尋、廣度優先搜尋、並查集;演算法搬運工、詳細解析、附完整題解程式碼)

力扣刷題筆記:547. 省份數量(三種方法實現:深度優先搜尋、廣度優先搜尋、並查集;演算法搬運工、詳細解析、附完整題解程式碼)

技術標籤:刷題筆記pythonleetcode

題目:

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/