310. Minimum Height Trees Add to List
2017-03-19 20:02
351 查看
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 ; 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; } } };
相关文章推荐
- LeetCode406. Queue Reconstruction by Height Add to List
- 【leedcode】 Add to List 617. Merge Two Binary Trees
- Add to List 310. Minimum Height Trees
- Add to List 617. Merge Two Binary Trees
- Add to List 617. Merge Two Binary Trees
- 第一次安装android studio时候弹出unable to access android sdk add-on list解决方法
- 第一次安装Android studio时候弹出unable to access android sdk add-on list的问题
- Add to List 371. Sum of Two Integers
- 【链表】链表的逆序【Add to List 206. Reverse Linked List】
- How to add a new "CustomAction" in ECB for a specific list
- How to modify non-customizable entity in MS Dynamics CRM 4.0 (Add Product price column to Price List Item view)
- LeetCode- Add to List 84. Largest Rectangle in Histogram
- LeetCode-Add to List 494. Target Sum
- Problem Code: PSHTTR Add problem to Todo list Submit Tweet
- How do I add elements to a Scala List?
- [leetcode] Add to List 169. Majority Element
- instance method '-AddList:' not found (return type defaults to 'id')---- iOS开发之最灵异事件之6
- add "remote-notification" to the list of your supported UIBackgroundModes in your Info.plist.
- 安装android studio时候弹出unable to access android sdk add-on list解决方法
- leetcode 21. Merge Two Sorted Lists Add to List