一个节点的”高度”是由距离最远的叶子节点决定的,单独计算一个节点的“高度”是O(n)的,计算所有的节点就是O(n^2)的,这其中有很多重复的工作,但是并不是很容易优化。
特殊的是所有叶子节点的“高度”都是1,而第二层叶子节点的“高度”是2,依次增加,直到树的中央,我想这也是样例输入没有把树画成传统样子的原因,就是在提示树中央的节点就是最深的节点,也是“高度”最大的节点。所以,先找到所有叶子节点(度为1),然后把他们都干掉,同时检查与他们相连的节点是不是新的叶子节点,反复这样会一层一层地拨开树。到达中央的条件是只剩下1个或者2个节点。
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
if (n == 1) return {0};
vector<unordered_set<int>> links(n);
for (auto edge : edges) {
links[edge.first].insert(edge.second);
links[edge.second].insert(edge.first);
}
queue<int> q;
for (int i=0;i<n;++i) {
if (links[i].size() == 1) {
q.push(i);
}
}
while (n>2) {
int numLeaf = q.size();
n -= numLeaf;
while(numLeaf--) {
int leaf = q.front(); q.pop();
for (auto node : links[leaf]) {
links[node].erase(leaf);
if (links[node].size() == 1) {
q.push(node);
}
}
}
}
vector<int> res;
while(!q.empty()) {
res.push_back(q.front());
q.pop();
}
return res;
}
};