310. Minimum Height Trees Add to List

来源:互联网 发布:淘宝搜索热度 编辑:程序博客网 时间:2024/06/03 17:42

LeetCode

  • 题目地址:https://leetcode.com/problems/minimum-height-trees/#/description
  • 思考过程:

    • 题目要求是给一个具有树的属性的无向图,即每个点仅被另一条边连在一起,也就是说对于n个节点的图,只有n-1条边。题目目的是要找到其中一个节点作为根节点,能使得整个树的高度最小,这样的树叫做Minimum Height Tree(MHT)。
    • 于是我一开始的想法很简单,(1)先根据输入构造边的一个map,(2)然后对从第0~n-1节点,计算一次深度,(3)最后根据深度的大小来返回MHT的根节点。但是这么做会在n=1000左右的时候超时,时间复杂度应该是O(n2),因为一共有n个点,每个点计算以它为根的深度,通过BFS来计算,复杂度是O(V+2E),因为是无向图每条边最多需要判断两次,每个点遍历一次,而V=n,E=n-1,复杂度即O(n),这样的过程有n次
    • 然后参考了一下solution,只看了一下人家的思路,然后自己理解后写,思路大概是这样的,每次找到只有一条边连着的节点,剔除它,并剔除所有和他相连的边,最后剩下一个点或者两个点(一起连着,都是MHT的根节点),对于这个的时间复杂度就是O(V+E),因为对于每个点只访问一次,并且删除,同时对于每个边删除一次,由于V=n,E=n-1,所以O(n)
    • 最后我的代码和答案的代码的对比,最主要的区别就是存储的时候,我用的是map,而答案用的是vector。这里我用map的原因是,每次检查到与该节点连接的边个数只有1的时候,需要把该节点删除,而map删除比vector快。但是答案的思路应该是每个节点只有一次机会,边数会变成1(变成是一个过程,从2然后erase一条边之后变成1),而之前边数是1的点不需要删除,因为下次再到它的时候(一定会再到它,因为无向图边是双向的),它的边数从1变成0,不会被考虑进去,也即相当于删除了,而在这里他节省了一些时间,所以我的算法和它的应该在常数项中会有点区别,毕竟对于unordered_map这种哈希map的删除时间应该是O(1)的,那么每次计算,我的复杂度会多O(n),但是总共的复杂度仍然是O(n)
  • 代码
    这是最开始自己的思路,超时

class Solution {public:    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {        vector<int> v;         int min = INT_MAX;        //construct m        for (vector<pair<int,int>>::iterator it = edges.begin(), end = edges.end(); it != end; it++) {            int one = it->first, two = it->second;            m[one].push_back(two);            m[two].push_back(one);        }        bool visit[n];        for (int i = 0; i < n; i++) {            memset(visit,0,sizeof(visit));            int dep = depthWithNode(i,visit);            //cout << "i: " << i << " dep: " << dep << endl;            if (dep < min) {                v.clear();                v.push_back(i);                min = dep;            } else if (dep == min)                v.push_back(i);        }        return v;    }    //calculate depth with root node k    int depthWithNode(int k, bool* visit) {        //initial        clearCur();        clearNext();        cur.push(k);        visit[k] = true;        int height = 0;        while (!cur.empty()) {            height++;            while (!cur.empty()) {                int tmp = cur.front();                cur.pop();                for (int i = 0; i < m[tmp].size(); i++) {                    if (!visit[m[tmp][i]]) {                        next.push(m[tmp][i]);                        visit[m[tmp][i]] = true;                    }                }            }            cur = next;            clearNext();        }        return height;    }    void clearCur() {        while (!cur.empty())            cur.pop();    }    void clearNext() {        while (!next.empty())            next.pop();    }private:    map<int,vector<int>> m;    queue<int> cur;    queue<int> next;};

这是后来参考的思路,自己实现的,大概用时116ms

class Solution {public:    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {        vector<int> v(1,0);         //construct m        for (vector<pair<int,int>>::iterator it = edges.begin(), end = edges.end(); it != end; it++) {            int one = it->first, two = it->second;            m[one].insert(two);            m[two].insert(one);        }        while(m.size()) {            v.clear();            if (m.size() == 1) {                v.push_back(m.begin()->first);                break;            }            for (unordered_map<int,set<int>>::iterator it = m.begin(), end = m.end(); it != end; it++) {                if (it->second.size() == 1)                    v.push_back(it->first);            }            int leafSize = v.size();            for (int i = 0; i < leafSize; i++) {                for (set<int>::iterator it = m[v[i]].begin(), end = m[v[i]].end(); it != end; it++) {                    m[*it].erase(v[i]);                }                m.erase(v[i]);            }        }        sort(v.begin(),v.end());        return v;    }private:    unordered_map<int,set<int>> m;};

这是答案的代码,和我写的有一点点不同,不同在思路中写到了这里不重复,大概耗时43ms

class Solution { public:  vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {    // Initialize the undirected graph    vector<set<int>> adj(n);    for (vector<pair<int,int>>::iterator it = edges.begin(), end = edges.end(); it != end; it++) {      adj[it->first].insert(it->second);      adj[it->second].insert(it->first);    }    // Corner case    vector<int> current;    if (n == 1) {      current.push_back(0);      return current;    }    // Create first leaf layer    for (int i = 0; i < adj.size(); ++i) {      if (adj[i].size() == 1) {        current.push_back(i);      }    }    // BFS the graph    while (true) {      vector<int> next;      for (int node : current) {        for (int neighbor : adj[node]) {          adj[neighbor].erase(node);          if (adj[neighbor].size() == 1) next.push_back(neighbor);        }      }      if (next.empty()) return current;      current = next;    }  }};
0 0
原创粉丝点击