【LeetCode】547. Number of Provinces (Medium) (JAVA)
Subject address: https://leetcode.com/problems/number-of-provinces/
Title description:
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]
General idea
There are n cities, some of which are connected to each other, and some of them are not connected. If city a and city b are directly connected, and city b is directly connected to city c, then city a and city c are indirectly connected.
A province is a group of directly or indirectly connected cities, and the group does not contain other unconnected cities.
Give you an nxn matrix isConnected, where isConnected[i][j] = 1 means that the i-th city and the j-th city are directly connected, and isConnected[i][j] = 0 means that the two are not directly connected.
Returns the number of provinces in the matrix.
Problem-solving method
- Put all connected nodes into a set
- Merge the original set of the two nodes
- Finally, find the number of remaining sets
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;
}
}
Execution time: 6 ms, beating 20.20% of Java users
Memory consumption: 39.7 MB, beating 17.42% of Java users
optimization
- There is no need to know each element of the set, just calculate the number of sets.
- Adopt DFS (depth first search)
- For example, position i: 1. Set isConnected[i][i] to 0 to indicate that i has been traversed; 2. Traverse all positions connected to i until there is no connection
- Every time isConnected[i][i] == 1 means that all i-1 nodes in front are not connected to node i, all are an independent set
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);
}
}
}
Execution time: 1 ms, beating 99.49% of Java users
Memory consumption: 39.6 MB, beating 30.21% of Java users