Leetcode310. Minimum Height Trees (week5 — medium)
题目
For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.
示例
题目的含义是从给出的一个无向图中找出以哪一个节点为根结点,能够使得以该根结点构成的树的高度达到最小,然后输出存在的节点
分析
这一道题粗略一看不免还觉得比较简单,但是又想不出什么比较好的方法,最蠢的方法大概就是对每一个节点进行BFS从而找出树的最大深度,这样的话,时间消耗是V的二次方量级的,复杂度也是很高。所以就只能够考虑一棵树的构成过程了。这里解题的基本思路是:因为叶节点的特点是只有一个相邻的节点,因此可以先找出题目所给出的树的节点,然后再将这一些节点删去,将这一些被删除的节点的临界点成为新的叶的节点用另外的数据结构存储下来,而成为最小高度的根自然也就是没有叶节点的,也就是产生的新节点数目为0。因此按照这一个思路实现对应的算法即可。
题解
代码实现如下:
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
if(n == 1){
vector<int> zero = {0};
return zero;
}
if( n == 2){
vector<int> result;
result.push_back(edges[0].first);
result.push_back(edges[0].second);
return result;
}
set<int> node;
vector<set<int>> linkmatrix(n);
for(int i = 0; i < edges.size(); i++){
node.insert(edges[i].first);
node.insert(edges[i].second);
linkmatrix[edges[i].first].insert(edges[i].second);
linkmatrix[edges[i].second].insert(edges[i].first);
}
vector<int> *leaves = new vector<int> ();
for(int i = 0; i < linkmatrix.size(); i++){
if(linkmatrix[i].size() == 1){
leaves->push_back(i);
}
}
vector<int> *leaves_help = new vector<int>();
//find all leaves and remove them
/*for(auto i: leaves){
cout << i << " ";
}*/
while(1){
for(auto i: *leaves){
for(auto j:linkmatrix[i]){
linkmatrix[j].erase(i);
/*
找出新生成的叶节点
*/
if(linkmatrix[j].size() == 1){
leaves_help->push_back(j);
}
}
}
/*
当没有叶节点产生的时候也就说明只剩下根节点了。
*/
if(leaves_help->empty()){
return *leaves;
}
leaves->clear();
swap(leaves, leaves_help);
}
}
};
后记
- 尽管这一种方法是O(n)的方法,但是实际运行的效率却并不是很高,大概是因为set的删除操作太多了的缘故。
- 后来查看了这一道题的题后讨论,发现有一种比较巧的方法:
- 也就是寻找根的方法,因为根需要中和都没一个末点的距离,这样才能够使得树的高度最小
- 而这样的话也就说明了图中的每两条最长的路径,都会公用这些根节点(一个或者两个)
- 因此可以通过两次BFS来获取出根节点,然后再加以计算便可
- 相较上面的做法应该是有所改进的