您的位置:首页 > 其它

[Leetcode] Minimum Height Trees

2016-05-13 15:20 357 查看

Minimum Height Trees

For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.

如题,找出最小深度树。一开始没看清题,把问题想复杂了。注意第一句话:

For a undirected graph with tree characteristics,

输入的是具有树特性的无向图,所以肯定是无环图。返回值是根节点列表。

思路:

要使得生成树的深度最小,根节点应当选择内部点,而且应当是整个图的中心。问题是这样的中心点怎么找?这样的中心点又有多少个?题目有给提示:How many MHTs can a graph have at most? 。说实话,看到这样的提示,我并没有什么感觉…不妨先从中心点在哪里入手。中心点应该在图的longest path上。直观上还是很好理解的,根节点就应该取在最长路径的中心上。至于数学上,暂时还没想到要如何证明。想通了这一点,中心点的数目就不难想了:中心点有1个或者2个,若最长路的节点数为奇数,中心点有一个;若为偶数,中心点有两个。

第一个思路,找出longest path。任选一个节点进行搜索(广搜深搜均可),然后找出最深的路径 path1。容易证明,path1一定包含在longest_paht中,其长度小于等于最长路。如果从paht1的一个端点出发再搜索一次,就可以找到longest_paht了。所以这个方法需要two pass search

另一个思路。容易想象,边缘的节点(也即度数1的节点)不应当为root。所以,通过“层层剥”的方法最终一定可以找到中心点。这个思路的关键是发现中心点数不大于2,但是这一个思路很难发现这一点。有了这个约束条件,这个思路实现起来比前一个方便,而且这个算法的性能应该说比前一个好。

实现

class Solution(object):
def findMinHeightTrees(self, n, edges):
"""
:type n: int
:type edges: List[List[int]]
:rtype: List[int]
"""
# Adjacency list
adj = [set() for i in xrange(n)]
# Degree list
degree = [0 for i in xrange(n)]
for i, j in edges:
adj[i].add(j)
adj[j].add(i)
for i in xrange(n):
degree[i] = len(adj[i])

# Remove nodes level by level (the nodes' degree equal to 1 should be removed)
remain = set([i for i in xrange(n)])
while len(remain) > 2:
rm_record = []

for v in remain:
if degree[v] == 1:
# Record nodes that should be removed
rm_record.append(v)

for v in rm_record:
for u in adj[v]:
degree[u] -= 1
remain.remove(v)

return list(remain)

if __name__ == '__main__':
s = Solution()
print s.findMinHeightTrees(6, [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]])
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode