本题采用的思路是不断地逐层的删除叶子节点,从而最后只剩下子节点的方法。本题的结果最后只能是有一个最小根节点或者两个,不可能有三个的情况存在。
首先,我们将所有的节点的入度统计到表nums中,后用队列q将入度为一的节点统计至q中,然后对count进行判断,如果此时所有的点都入度为一,则此时q中的所有节点,有可能是一个或两个节点,都是最小根节点,写入list中。如果不是n,将所有的包含q中的节点的与之相连接的边的两一个节点入度-1,再次执行操作知道q中没有元素。
最后,必将count==n,返回的list就是所得的结果。代码及其注释如下:
int[][] edg;
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
edg = edges;
ArrayList<Integer> list = new ArrayList<Integer>();
if(n==0) return list;
if(n==1)
{
list.add(0);
return list;
}
int l = n-1;
int[] nums =new int[n]; //存储各个节点出现的次数,次数为1,则为叶节点,否则不是叶节点。
for (int i = 0; i < l; i++)
{
nums[edg[i][0]]++;
nums[edg[i][1]]++;
}//
int count =0;
while(true)
{
Queue<Integer> q =new LinkedList<Integer>();//存储叶子
for (int i = 0; i < nums.length; i++)
{
if(nums[i]==1){
q.add(i);
count++;
nums[i] = -1;
}else if(nums[i]==0){
list.add(i);
return list;
}
}//统计叶子的个数,如果是叶子,放入q中并且将标记置为-1;
if(count==n){
while(!q.isEmpty())
list.add(q.poll());
return list;
}//此情况为有两个最小根节点的情况,下面步骤为删除叶子,即改变nums的计数值
while(!q.isEmpty()){
int tag = q.poll();//逐次的从队列中拿取数
for (int i = 0; i <l; i++) {
if(edg[i][0]==tag){
if(nums[edg[i][1]]==-1)
continue;
else
nums[edg[i][1]]--;
}else if(edg[i][1]==tag)
{
if(nums[edg[i][0]]==-1)
continue;
else
nums[edg[i][0]]--;
}
}
}
}
}