[LeetCode]310. Minimum Height Trees

解法一:http://siukwan.sinaapp.com/?p=189    https://www.cnblogs.com/TonyYPZhang/p/5123058.html

1.这道题目主要是求一个无向图中,以哪个节点为根节点的树的高度最小;

2.常规方法可以使用BFS或者DFS,对每个点都遍历一遍,求出所有点组成的树的高度,然后找出哪些高度最小的节点,可以通过不断更新最低高度来进行剪枝。实际上我写了BFS和DFS的程序,均出现超时。

3.最终的解题思路采用了不断删除叶子节点,逐渐逼近根节点的方法,在删除叶子节点的同时,会有一些新的节点成为叶子节点,于是继续循环删除,直至不能删除为止,那么剩下的节点就是高度最小的根。

4.当n等于1时,需要特殊处理,直接返回{0}。

5.最终会剩下1个节点或者2个节点,1个节点的情况比较好理解,如{0,1}{0,2},同时删除了叶子节点1和2,就剩下0;而两个节点的情况为{0,1},此时0和1的邻居均为1,都是叶子节点,在下一轮操作后,0和1均没有邻居,所以这两个节点都是正确的答class Solution public:

struct TreeNode{
        set<int> list;//使用set结构方便删除邻居
        TreeNode(){};
        bool isLeaf(){return list.size()==1;};//这边的分号不能丢
    };//这个分号也不能丢
    
    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
        if(n==1) return {0};
        
        
        //使用节点来存储这棵树,耗费的空间为O(n+2e)
        vector<TreeNode> tree(n);
        for(auto edge:edges){
            tree[edge.first].list.insert(edge.second);
            tree[edge.second].list.insert(edge.first);
        }
        
        vector<int> node1(0),node2(0);//node1记录当前的叶子节点、node2记录删除node1叶子节点后,成为新的叶子节点的节点
        for(int i=0;i<tree.size();i++){
            if(tree[i].isLeaf()) node1.push_back(i);
        }
        
        while(1){
            for(auto leaf:node1){
                for(auto it=tree[leaf].list.begin();it!=tree[leaf].list.end();it++){//与叶子节点中所有相连的点。我觉得只有一个。
                    int neigh=*it;
                    tree[neigh].list.erase(leaf);//删除叶子节点
                    if(tree[neigh].isLeaf()) node2.push_back(neigh);//删除后,如果是叶子节点,则放到node2中
                }
            }
            
            if(node2.empty()) break;//遍历完后,如果node2为空,即node1中的节点不是叶子节点,要么是剩下一个节点,要么剩下两个相互连接的节点
            node1.clear();
            swap(node1,node2);
        }
        
        //if(node1.empty()) return node2;
        //else return node1;
        //node1中有两个节点,且互相连接,邻居都为1,所以被压进node2中(此时邻居都被清除),然后在下一轮循环,两者都不被视为叶子节点
        //node1中只剩下1个节点,因为邻居为空,所以不能压进node2中
        return node1;//应该是只要返回node1就行了,node2永远是空的。
} };

 

另外一种代码:指针得稍微理解一下

class Solution {
public:
    class TNode{
        public:
        int val;
        unordered_set<TNode*>neighbours;
        TNode(int val):val(val){};
        bool isLeaf(){return neighbours.size()==1;};
    };//加分号
    
    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
        map<int,TNode*> val_nodes;
        for(int i=0;i<n;i++){
            TNode* temp = new TNode(i);
            val_nodes[i]=temp;
        }
        
        for(auto edge:edges){
            val_nodes[edge.first]->neighbours.insert(val_nodes[edge.second]);
            val_nodes[edge.second]->neighbours.insert(val_nodes[edge.first]);
        }
        
        while(val_nodes.size()>2){
            list<TNode*>listq;
            for(auto it=val_nodes.begin();it!=val_nodes.end();it++){
                if(it->second->isLeaf()) listq.push_back(it->second);
            }
            
            for(auto it=listq.begin();it!=listq.end();it++){
                TNode* p= *(*it)->neighbours.begin();//it是list的指针,所以要用(*it)转为TNode
                p->neighbours.erase(*it);
                (*it)->neighbours.erase(p);
                val_nodes.erase((*it)->val);
            }
        }
        vector<int> res;
        for(auto it=val_nodes.begin();it!=val_nodes.end();it++){
            res.push_back(it->first);
        }
        return res;
    }
};
View Code

 

posted @ 2018-09-10 16:21  小飞飞v21  阅读(112)  评论(0编辑  收藏  举报