Leetcode310. Minimum Height Trees

A tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.

Given a tree of n nodes labelled from 0 to n - 1, and an array of n - 1 edges where edges[i] = [ai, bi] indicates that there is an undirected edge between the two nodes ai and bi in the tree, you can choose any node of the tree as the root. When you select a node x as the root, the result tree has height h. Among all possible rooted trees, those with minimum height (i.e. min(h))  are called minimum height trees (MHTs).

Return a list of all MHTs' root labels. You can return the answer in any order.

The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.

 

Example 1:

Input: n = 4, edges = [[1,0],[1,2],[1,3]]
Output: [1]
Explanation: As shown, the height of the tree is 1 when the root is the node with label 1 which is the only MHT.

Example 2:

Input: n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
Output: [3,4]

Example 3:

Input: n = 1, edges = []
Output: [0]

Example 4:

Input: n = 2, edges = [[0,1]]
Output: [0,1]

 

Constraints:

  • 1 <= n <= 2 * 104
  • edges.length == n - 1
  • 0 <= ai, bi < n
  • ai != bi
  • All the pairs (ai, bi) are distinct.
  • The given input is guaranteed to be a tree and there will be no repeated edges.

 

思路:

首先确定可以有几个root,本质上是找最长的线,而理想root就是线的中点,因此如果最长线上有偶数个node则root为2,否则为1。

用BFS进行一层层剥离。这里涉及一个问题,是从edge最多的点开始剥离还是从edge最少的点开始剥离,答案是最少的点,因为edge最多的点可能有好几个,这时候无法分辨哪个应该作为理想的root。

用unordered_map<int,unordered_set<int>>储存图,这里也可以用vector<unrodered_set<int>>来存,index为0到n-1,不过因为最后return的vector中不讲究顺序(哈希表的遍历顺序是无序的),3,4和4,3一样,所以用哈希map也可。因为是双向图,1->3的同时3->1。

遍历图,如果某个节点只有1个edge,加入queue,之后进行常规的BFS,但是这里while条件应为图中size>2而不是queue.size()>0。BFS中每次都删掉queue中的edge,同时如果删完后的node只有单edge,加入queue。

 

代码:

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        if(n==1)
            return {0};
        unordered_map<int,unordered_set<int>> m;
        for(auto &e:edges)
        {
            m[e[0]].insert(e[1]);
            m[e[1]].insert(e[0]);
        }
        queue<int> q;
        for(auto itr=m.begin();itr!=m.end();itr++)
        {
            if(itr->second.size()==1)
            {
                q.push(itr->first);
            }
        }
        while(m.size()>2)
        {
            int len=q.size();
            for(int i=0;i<len;i++)
            {
                auto temp=q.front();
                q.pop();
                int f=temp;
                int s=*m[temp].begin();
                m.erase(f);
                m[s].erase(f);
                if(m[s].size()==1)
                    q.push(s);
            }
        }
        vector<int> res;
        for(auto itr=m.begin();itr!=m.end();itr++)
            res.push_back(itr->first);
        return res;
        
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值