leetcode-547 省份数量
没啥好说的,并查集模板题。我感觉并查集的精髓就体现在find和merge两个函数的递归操作里。
class Solution {
public:
int fa[200];
void init(int n){
for(int i = 0; i < n; ++i) fa[i] = i;
}
int find(int x){
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
void merge(int x, int y){
fa[find(x)] = find(y);
}
int findCircleNum(vector<vector<int>>& isConnected) {
int n = isConnected.size();
init(n);
for(int i = 0; i < n; ++i){
for(int j = i + 1; j < n; ++j){
if(isConnected[i][j] == 1) merge(i, j);
}
}
int ans = 0;
for(int i = 0; i < n; ++i){
if(fa[i] == i) ++ans;
}
return ans;
}
};
leetcode-310 最小高度树
这道题思路就是从度为1的节点开始一层一层剥洋葱,跟拓扑排序基本一样。
需要想一下的点:
- 首先树是无向图,而无向图其实也就是双向图,一条边的两个节点都需要统计到。
- 其次是按照思路一层层剥下去,但并没有一个明显的停止条件,满足达到这个停止条件之后树中剩下的节点都是结果。因此需要用一个结果集每一“层”暂存当前节点,每次进入循环则清空——当不满足进入循环的条件,也就是该结束了的时候,结果集中剩下的就是结果。
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
if(n == 1) return {0};
vector<int> degree(n);
vector<vector<int>> conn(n);
for(auto& edge : edges){
int a = edge[0], b = edge[1];
conn[a].push_back(b);
conn[b].push_back(a);
++degree[a];
++degree[b];
}
deque<int> q;
for(int i = 0; i < n; ++i){
if(degree[i] == 1) q.push_back(i);
}
vector<int> iteration;
while(!q.empty()){
iteration.clear();
int len = q.size();
for(int i = 0; i < len; ++i){
int node = q.front();
q.pop_front();
iteration.push_back(node);
vector<int>& this_conn = conn[node];
for(int nx : this_conn){
--degree[nx];
if(degree[nx] == 1) q.push_back(nx);
}
}
}
return iteration;
}
};