您的位置:首页 > 其它

【LeetCode】310. Minimum Height Trees

2016-06-04 14:29 393 查看

题目链接

思路

我想到了n个点构成树,那么一定会有n-1条边,构成的树深度最大的情况发生在所有点位于一条链上,此时深度为 n/2 或 n/2+1 ,这取决于n的奇偶性。

树深度最浅的情况发生在一个根节点,所有其它节点都与根节点直接相连,此时深度为2。

我还发现一个规律,就是叶子节点的数目+树的最长路径为一定值,为节点数+2。这样统计出有多少个叶子节点后,再走最长路径的一半所到达的节点就是根节点。但是这个思路不能保证走最长路径的一半是正确的路径,所以这个方法没有再进行下去。

Hot解法是利用bfs,从叶子节点开始访问,每一次循环都把与叶子节点直接相连的节点访问,并判断它们是否成为新的叶子节点。同时从叶子节点出发,最终共同到达的节点一定是根节点。

代码

vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
vector<int> re;
if (n<=2){
for (int i=0;i<n;++i){
re.push_back(i);
}
return re;
}
vector<unordered_set<int>> graph(n);
for (int i=0;i<edges.size();++i){
auto p = edges[i];
graph[p.first].insert(p.second);
graph[p.second].insert(p.first);
}
//find all leaves
queue<int> leaves;
for (int i=0;i<n;++i){
if (graph[i].size()==1) leaves.push(i);
}

while(n>2){
n = n - leaves.size();
queue<int> newLeaves;
while (!leaves.empty()){
int curLeaf = leaves.front();
leaves.pop();
int nextToLeaf = *(graph[curLeaf].begin());
graph[nextToLeaf].erase(curLeaf);
if (graph[nextToLeaf].size()==1){
newLeaves.push(nextToLeaf);
}
}
leaves = newLeaves;
}
while (!leaves.empty()){
int leaf = leaves.front();
leaves.pop();
re.push_back(leaf);
}
return re;
}


细节

第一次我用向量存储每个节点的相邻节点,后来发现vector删除指定大小的元素不是很方便,vector只有两种删除方式,erase是删除基于位置的,pop_back()只能删除最后一个元素。所以后来改用set
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode