[LeetCode] 547. Friend Circles

There are n cities. Some of them are connected, while some are not. If city a is connected directly with city b, and city b is connected directly with city c, then city a is connected indirectly with city c.

A province is a group of directly or indirectly connected cities and no other cities outside of the group.

You are given an n x n matrix isConnected where isConnected[i][j] = 1 if the ith city and the jth city are directly connected, and isConnected[i][j] = 0 otherwise.

Return the total number of provinces.

 

Example 1:

Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
Output: 2

Example 2:

Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
Output: 3

Constraints:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] is 1 or 0.
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

省份数量。

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-provinces
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这是一道典型的 union find 的题目,找图里面有多少个连通分量。我这里给出两种解法,一种 DFS 的解法,一种 union find 的解法。

DFS做法的思路是创建一个长度为 n 的数组,记录每个人是否被访问过,如果某个人没有被访问过,则对其做 DFS 遍历,同时 count++,因为即使这个人没有朋友,他也可以自成一个朋友圈。DFS 递归调用的时候,判断当前的人 i 和其他所有人的关系,并且记得每当遍历过一个人的时候,先把他标记成访问过,否则会 stack overflow。

时间O(n^2)

空间O(n)

Java实现

 1 class Solution {
 2     int n;
 3     
 4     public int findCircleNum(int[][] isConnected) {
 5         n = isConnected.length;
 6         boolean[] visited = new boolean[n];
 7         int count = 0;
 8         for (int i = 0; i < n; i++) {
 9             if (!visited[i]) {
10                 dfs(isConnected, visited, i);
11                 count++;
12             }
13         }
14         return count;
15     }
16     
17     private void dfs(int[][] isConnected, boolean[] visited, int i) {
18         for (int j = 0; j < n; j++) {
19             if (i == j) {
20                 continue;
21             }
22             if (!visited[j] && isConnected[i][j] == 1) {
23                 visited[j] = true;
24                 dfs(isConnected, visited, j);
25             }
26         }
27     }
28 }

 

Union Find的做法需要依赖一个class。我这里同时提供两个帖子,一个有并查集的图解,一个有并查集的代码模板。代码中rank的意思是每个联通分量的大小,如果两个集合是联通的,我们尽量把小的放进大的里面。

时间O(V * E)

空间O(n)

Java实现

 1 class Solution {
 2     class UnionFind {
 3         // rank[i]表示以i为根节点的树的高度
 4         private int[] parent, rank;
 5         private int count;
 6         
 7         public UnionFind(int n) {
 8             parent = new int[n];
 9             rank = new int[n];
10             count = n;
11             for (int i = 0; i < n; i++) {
12                 parent[i] = i;
13                 rank[i] = 1;
14             }
15         }
16         
17         public int find(int p) {
18             // path compression
19             // 当前节点遍历时将节点指向父亲的父亲节点
20             while (p != parent[p]) {
21                 parent[p] = parent[parent[p]];
22                 p = parent[p];
23             }
24             return p;
25         }
26         
27         public void union(int p, int q) {
28             int rootP = find(p);
29             int rootQ = find(q);
30             if (rootP == rootQ) {
31                 return;
32             }
33             // 这里合并的时候判断树的高度,将其高度低的节点指向高度高的根节点
34             if (rank[rootP] > rank[rootQ]) {
35                 parent[rootQ] = rootP;
36                 rank[rootP] += rank[rootQ];
37             } else {
38                 parent[rootP] = rootQ;
39                 rank[rootQ] += rank[rootP];
40             }
41             count--;
42         }
43         
44         public int count() {
45             return count;
46         }
47     }
48     
49     public int findCircleNum(int[][] isConnected) {
50         int n = isConnected.length;
51         UnionFind uf = new UnionFind(n);
52         for (int i = 0; i < n; i++) {
53             for (int j = i + 1; j < n; j++) {
54                 if (isConnected[i][j] == 1) {
55                     uf.union(i, j);
56                 }
57             }
58         }
59         return uf.count();
60     }
61 }

 

相关题目

261. Graph Valid Tree

323. Number of Connected Components in an Undirected Graph

547. Friend Circles

LeetCode 题目总结

posted @ 2020-04-17 06:02  CNoodle  阅读(198)  评论(0编辑  收藏  举报