目录
- 题目描述
- 分析
- 代码
题目描述
分析
这道题很容易想到用dfs分别求出每棵树的高度,再取最小值,但是这样复杂度太高了,最后一个样例怎么都不能通过,于是只好另辟蹊径,参考了别人的博客,学到了一种新的算法,就是逐步删除叶子节点,直到没有可删除的节点,剩下的这个/些节点就是答案。
首先用map把图表示成有向图:
map<int, set<int>> mat;
for(auto i : edges) {
mat[i.first].insert(i.second);
mat[i.second].insert(i.first);
}
在这里,出度为一的点就是叶子节点:
vector<int> leaves;
for(auto i : mat) {
if(i.second.size() == 1) {
leaves.push_back(i.first);
}
}
然后开始删除叶子节点,在删除节点的同时,更新与之相连的其它节点,同时用另一个数组存储新产生的叶子节点,循环往复,直到只剩下一个或两个节点:
while(n > 2) {
n -= leaves.size();
vector<int> new_leaves;
for(auto i : leaves) {
auto next = mat[i];
for(auto j : next) {
mat[i].erase(j);
mat[j].erase(i);
if(mat[j].size() == 1) {
new_leaves.push_back(j);
}
}
}
leaves = new_leaves;
}
代码
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
if(n == 1) {
return {0};
}
map<int, set<int>> mat;
for(auto i : edges) {
mat[i.first].insert(i.second);
mat[i.second].insert(i.first);
}
vector<int> leaves;
for(auto i : mat) {
if(i.second.size() == 1) {
leaves.push_back(i.first);
}
}
while(n > 2) {
n -= leaves.size();
vector<int> new_leaves;
for(auto i : leaves) {
auto next = mat[i];
for(auto j : next) {
mat[i].erase(j);
mat[j].erase(i);
if(mat[j].size() == 1) {
new_leaves.push_back(j);
}
}
}
leaves = new_leaves;
}
return leaves;
}
};