[leetcode]547.省份數量
阿新 • • 發佈:2021-01-17
技術標籤:LeetCode
有 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]
思路1:圖的遍歷
isConnected為圖的鄰接矩陣。從第一個點開始進行dfs或bfs,每一次遍歷即一個聯通分量(省份),統計有幾個聯通分量返回即可。
AC程式碼(C++):
//dfs
class Solution {
public:
void dfs(vector<vector<int>>& isConnected, vector<int>& visited, int cities,
int i) { //是否連線,是否訪問,
for (int j = 0; j < cities; j++) {
if (isConnected[i][j] == 1 && visited[j] == 0) {
//如果i,j之間有邊並且j沒有訪問過
visited[ j] = 1; //訪問j
dfs(isConnected, visited, cities, j); //遞迴
}
}
}
int findCircleNum(vector<vector<int>>& isConnected) {
int cities = isConnected.size(); //城市數量
vector<int> visited(cities); //訪問標記陣列
int provinces = 0; //省份數量
for (int i = 0; i < cities; i++) {
if (visited[i] == 0) {
dfs(isConnected, visited, cities, i); //從第i個點開始遍歷
provinces++; //一次dfs代表一次聯通分量,即一個省份
}
}
return provinces;
}
};
// bfs
class Solution {
public:
int findCircleNum(vector<vector<int>>& isConnected) {
int cities = isConnected.size();
vector<int> visited(cities);
int province = 0;
queue<int> Q;
for (int i = 0; i < cities; i++) {
if (visited[i] == 0) {
Q.push(i);
while (!Q.empty()) {
int j = Q.front(); //出隊
Q.pop();
visited[j] = 1; //訪問隊頭元素
for (int k = 0; k < cities; k++) {
//遍歷所有與j相鄰的元素
if (isConnected[j][k] == 1 && visited[k] == 0) {
Q.push(k); //入隊。
}
}
}
province++; //一次bfs為一個聯通向量
}
}
return province;
}
};
思路2:並查集
計算連通分量數的另一個方法是使用並查集。初始時,每個城市都屬於不同的連通分量。遍歷矩陣isConnected,如果兩個城市之間有相連關係,則它們屬於同一個連通分量,對它們進行合併。
AC程式碼:(c++)
class Solution {
public:
int Find(vector<int>& parent, int index) {
if (parent[index] != index) {
parent[index] = Find(parent, parent[index]);
}
return parent[index];
}
void Union(vector<int>& parent, int index1, int index2) {
parent[Find(parent, index1)] = Find(parent, index2); //合併
}
int findCircleNum(vector<vector<int>>& isConnected) {
int cities = isConnected.size();
vector<int> parent(cities); //最開始每一個都是單獨的集合
for (int i = 0; i < cities; i++) {
parent[i] = i;
}
for (int i = 0; i < cities; i++) {
for (int j = i + 1; j < cities; j++) {
if (isConnected[i][j] == 1) { //兩點間有聯通則合併
Union(parent, i, j);
}
}
}
int provinces = 0;
for (int i = 0; i < cities; i++) {
if (parent[i] == i) {
provinces++; //查詢有幾個根節點
}
}
return provinces;
}
};