1. 程式人生 > 其它 >[leetcode]547.省份數量

[leetcode]547.省份數量

技術標籤: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;
  }
};