【LeetCode】547. Number of Provinces 省份数量(Medium)(JAVA)
题目地址: https://leetcode.com/problems/number-of-provinces/
题目描述:
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 i-th city and the j-th 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 表示二者不直接相连。
返回矩阵中 省份 的数量。
解题方法
- 把所有相连的节点放到一个集合当中
- 把两个节点原本的集合合并
- 最后求出剩下的集合个数
class Solution {
public int findCircleNum(int[][] isConnected) {
List<Set<Integer>> list = new ArrayList<>();
for (int i = 0; i < isConnected.length; i++) {
for (int j = 0; j < isConnected[0].length; j++) {
if (isConnected[i][j] == 0) continue;
merge(list, i, j);
}
}
return list.size();
}
public void merge(List<Set<Integer>> list, int num1, int num2) {
Set<Integer> set1 = getPre(list, num1);
Set<Integer> set2 = getPre(list, num2);
if (set1 == null && set2 == null) {
Set<Integer> temp = new HashSet<>();
temp.add(num1);
temp.add(num2);
list.add(temp);
} else if (set1 == null) {
set2.add(num1);
list.add(set2);
} else if (set2 == null) {
set1.add(num2);
list.add(set1);
} else {
set1.addAll(set2);
list.add(set1);
}
}
public Set<Integer> getPre(List<Set<Integer>> list, int num) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).contains(num)) return list.remove(i);
}
return null;
}
}
执行耗时:6 ms,击败了20.20% 的Java用户
内存消耗:39.7 MB,击败了17.42% 的Java用户
优化
- 这里不需要知道集合每个的元素,只需要计算出集合的个数即可
- 采用 DFS(深度优先搜索)
- 如位置 i: 1、把 isConnected[i][i] 置位 0 表示 i 已经遍历过了;2、遍历所有和 i 相连的位置,知道没有相连的为止
- 每次 isConnected[i][i] == 1 表示前面的所有 i - 1 个节点都不和 i 节点相连,所有是一个独立的集合
class Solution {
public int findCircleNum(int[][] isConnected) {
int res = 0;
for (int i = 0; i < isConnected.length; i++) {
if (isConnected[i][i] == 0) continue;
fH(isConnected, i);
res++;
}
return res;
}
public void fH(int[][] isConnected, int index) {
if (isConnected[index][index] == 0) return;
isConnected[index][index] = 0;
for (int i = 0; i < isConnected.length; i++) {
if (isConnected[index][i] == 0) continue;
fH(isConnected, i);
}
}
}
执行耗时:1 ms,击败了99.49% 的Java用户
内存消耗:39.6 MB,击败了30.21% 的Java用户