题目
树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。
给你一棵包含 n 个节点的树,标记为 0 到 n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表(每一个边都是一对标签),其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条无向边。
可选择树中任何一个节点作为根。当选择节点 x 作为根节点时,设结果树的高度为 h 。在所有可能的树中,具有最小高度的树(即,min(h))被称为 最小高度树 。
请你找到所有的 最小高度树 并按 任意顺序 返回它们的根节点标签列表。
树的 高度 是指根节点和叶子节点之间最长向下路径上边的数量。
示例 1:
输入:n = 4, edges = [[1,0],[1,2],[1,3]]
输出:[1]
解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。
示例 2:
输入:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
输出:[3,4]
提示:
- 1 <= n <= 2 * 104
- edges.length == n - 1
- 0 <= ai, bi < n
- ai != bi
- 所有 (ai, bi) 互不相同
- 给定的输入 保证 是一棵树,并且 不会有重复的边
答案
暴力解法
class Solution {
public:
int queue[80000], queue1[80000];
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) { //打印所有深度为1/2树最大深度的节点
//3次bfs确定最大深度
//在第3次bfs确定最大深度的同时寻找关键路径(组成最大深度的两个节点)上深度为1/2的节点
vector<int> net[80000];
for(int i=0;i<edges.size();i++) {
net[edges[i][0]].push_back(edges[i][1]);
net[edges[i][1]].push_back(edges[i][0]);
}
if(n==1) {
return {0};
}
int basenode = net[0][0];
int maxpath;
unordered_set<int> buf;
std::queue<int> next;
maxpath = 0;
queue[basenode] = 0;
buf.insert(basenode);
next.push(basenode);
while(!next.empty()) {
int levelsize = next.size();
for(int i=0;i<levelsize;i++) {
int tmpfront = next.front();
next.pop();
for(auto j : net[tmpfront]) {
if(buf.count(j)==0) {
queue[j] = queue[tmpfront] + 1;
if(queue[j]>maxpath) {
basenode = j;
maxpath = queue[j];
}
next.push(j);
buf.insert(j);
}
}
}
}
buf.clear();
maxpath = 0;
queue[basenode] = 0;
buf.insert(basenode);
next.push(basenode);
while(!next.empty()) {
int levelsize = next.size();
for(int i=0;i<levelsize;i++) {
int tmpfront = next.front();
next.pop();
for(auto j : net[tmpfront]) {
if(buf.count(j)==0) {
queue[j] = queue[tmpfront] + 1;
if(queue[j]>maxpath) {
basenode = j;
maxpath = queue[j];
}
next.push(j);
buf.insert(j);
}
}
}
}
buf.clear();
vector<int> ans;
queue1[basenode] = 0;
if((queue1[basenode]==(maxpath+maxpath%2)/2 && queue[basenode]==maxpath/2) || (queue1[basenode]==maxpath/2 && queue[basenode]==(maxpath+maxpath%2)/2)) {
ans.push_back(basenode);
}
buf.insert(basenode);
next.push(basenode);
while(!next.empty()) {
int levelsize = next.size();
for(int i=0;i<levelsize;i++) {
int tmpfront = next.front();
next.pop();
for(auto j : net[tmpfront]) {
if(buf.count(j)==0) {
queue1[j] = queue1[tmpfront] + 1;
if((queue1[j]==(maxpath+maxpath%2)/2 && queue[j]==maxpath/2) || (queue1[j]==maxpath/2 && queue[j]==(maxpath+maxpath%2)/2)) { // || (queue1[j]==(maxpath+maxpath%2)/2 && queue[j]==(maxpath+maxpath%2)/2) || (queue1[j]==maxpath/2 && queue[j] == maxpath/2) 不存在
ans.push_back(j);
}
next.push(j);
buf.insert(j);
}
}
}
}
buf.clear();
return ans;
}
};
一份第70/71测试用例超时的代码
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) { //打印所有深度为1/2树最大深度的节点
//遍历搜索确定最大深度
if(n==1) {
return {0};
}
vector<int> queue = vector<int>(n, 0);
int basenode = edges[0][0];
int maxpath = 0;
queue[basenode] = 0;
unordered_set<int> buf;
buf.insert(basenode);
while(buf.size() < n) {
for(int i = 0; i < edges.size();i++) {
if(buf.count(edges[i][0]) == 1 && buf.count(edges[i][1])==0) {
buf.insert(edges[i][1]);
queue[edges[i][1]] = queue[edges[i][0]] + 1;
}
else if(buf.count(edges[i][1]) == 1 && buf.count(edges[i][0])==0) {
buf.insert(edges[i][0]);
queue[edges[i][0]] = queue[edges[i][1]] + 1;
}
}
}
for(int i = 0; i < queue.size(); i++) {
if(queue[i]>maxpath) {
maxpath = queue[i];
basenode = i;
}
}
buf.clear();
queue[basenode] = 0;
buf.insert(basenode);
while(buf.size() < n) {
for(int i = 0; i < edges.size();i++) {
if(buf.count(edges[i][0]) == 1 && buf.count(edges[i][1])==0) {
buf.insert(edges[i][1]);
queue[edges[i][1]] = queue[edges[i][0]] + 1;
}
else if(buf.count(edges[i][1]) == 1 && buf.count(edges[i][0])==0) {
buf.insert(edges[i][0]);
queue[edges[i][0]] = queue[edges[i][1]] + 1;
}
}
}
int basenode1 = basenode;
maxpath = 0;
for(int i = 0; i < queue.size(); i++) {
if(queue[i]>maxpath) {
maxpath = queue[i];
basenode1 = i;
}
}
buf.clear();
vector<int> queue1 = vector<int>(n, 0);
queue1[basenode1] = 0;
//unordered_set<int> buf;
buf.insert(basenode1);
//buf.insert(edges[0][1]);
while(buf.size() < n) {
for(int i = 0; i < edges.size();i++) {
if(buf.count(edges[i][0]) == 1 && buf.count(edges[i][1])==0) {
buf.insert(edges[i][1]);
queue1[edges[i][1]] = queue1[edges[i][0]] + 1;
}
else if(buf.count(edges[i][1]) == 1 && buf.count(edges[i][0])==0) {
buf.insert(edges[i][0]);
queue1[edges[i][0]] = queue1[edges[i][1]] + 1;
}
}
}
//寻找关键路径上深度为1/2的节点
vector<int> ans;
for(int i = 0; i < queue.size(); i++) {
if((queue[i]==maxpath/2 || queue[i]==(maxpath+maxpath%2)/2) && (queue1[i]==maxpath/2 || queue1[i]==(maxpath+maxpath%2)/2)) {
ans.push_back(i);
}
}
return ans;
}
};