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.
Format
The graph contains n
nodes which are labeled from 0
to n - 1
. You will be given the number n
and a list of undirected edges
(each edge is a pair of labels).
You can assume that no duplicate edges will appear in edges
. Since all edges are undirected, [0, 1]
is the same as [1, 0]
and thus will not appear together in edges
.
Example 1:
Given n = 4
, edges = [[1, 0], [1, 2], [1, 3]]
0 | 1 / \ 2 3
return [1]
题目是说从无向图里找一个或几个节点做根节点,使得高度最小。
这题似乎可以一路反证法过去。。我说似乎是因为我没有严格证明。。。
首先这个节点是1个或者2个。考虑3个的情况,那么中间那个节点对左或右的高度肯定至少是另外两个节点高度+1,因此不成立。
考虑一个MHT树,由树最底层的叶节点出发可以得到一条最长路。
根节点一定在这棵树最长路上,不然,由于根节点不在最长路上,那么根节点到最底层叶节点的路径会增加,MHT树不成立。
再考虑根节点在这条最长路上的位置,由于要树高度最短,因此根节点一定是这条路上的中间节点。
因此解题的关键就是从叶节点出发找到一条最长路,输出中间节点。
这里有两个case要注意,一个是从任意叶节点出发不一定能找到最长路, 一个是遍历所有叶节点找最长路会超时。
给出的方法是从任意一个叶节点出发找到这个叶节点对应的最长路,再从这条路另一头的叶节点出发,如果得到的最长路长度相等,就停止,输出根节点
否则当长度更长时继续。
当然这个方法没有严格证明,,可能就是个小trick。。就这样还能超过83%的人的运行时间。。。。。
class Solution { public: void dfs(vector<int> &re,vector<vector<int> > &g,int *statue,int pre_node,vector<int> &pre_list){ if(g[pre_node].size()==1 && statue[g[pre_node][0]]==1){ if(pre_list.size()>re.size()) re=pre_list; return; } int tmp_node; for(int i=0;i<g[pre_node].size();i++){ tmp_node=g[pre_node][i]; if(statue[tmp_node]==1) continue; pre_list.push_back(tmp_node); statue[tmp_node]=1; dfs(re,g,statue,tmp_node,pre_list); pre_list.pop_back(); statue[tmp_node]=0; } } vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) { int *statue = new int[n]; // int *no_node = new int[n]; memset(statue,0,sizeof(int)*n); // memset(no_node,0,sizeof(int)*n); vector<vector<int> > g(n); vector<int> re,pre_list; int a,b; for(int i=0;i<edges.size();i++){ a = edges[i].first; b = edges[i].second; g[a].push_back(b); g[b].push_back(a); } int next_node; for(int i=0;i<g.size();i++) if(g[i].size()==1) { next_node = i; break; } int long_path=0; while(n>1 && (re.size()>long_path || re.size()==0)){ long_path=re.size(); statue[next_node]=1; // no_node[g[i][0]]=1; pre_list.push_back(next_node); dfs(re, g, statue,next_node,pre_list); statue[next_node]=0; pre_list.pop_back(); next_node=re.back(); } if(re.size()==0) return vector<int> {0}; if(re.size()%2==1) return vector<int> {re[re.size()/2]}; if(re.size()%2==0){ if(re.size()/2<re.size()/2-1) swap(re[re.size()/2],re[re.size()/2-1]); return vector<int> {re[re.size()/2-1],re[re.size()/2]}; } } };