计算任意(非二进制)树的高度

时间:2018-05-02 00:38:26

标签: python algorithm data-structures tree

我目前正在参加在线数据结构课程,这是家庭作业之一;请指导我找到答案,而不是给我答案。

提示如下:

  

任务。您将获得有根树的说明。您的任务是计算并输出其高度。回想一下(带根)树的高度是节点的最大深度,或者从叶子到根的最大距离。您将获得一个任意树,不一定是二叉树。

     

输入格式。第一行包含节点数 n 。第二行包含从-1到 n-1 节点父节点的整数。如果 i - 其中一个(0≤i≤n-1)为-1,则节点 i 为根,否则为 i -th节点的父节点的从0开始的索引。保证只有一个根。保证输入代表树。

     

约束。1≤ n ≤10 5

我当前的解决方案有效,但是当n>时非常慢10 2 。这是我的代码:

# python3

import sys
import threading

# In Python, the default limit on recursion depth is rather low,
# so raise it here for this problem. Note that to take advantage
# of bigger stack, we have to launch the computation in a new thread.
sys.setrecursionlimit(10**7)  # max depth of recursion
threading.stack_size(2**27)   # new thread will get stack of such size
threading.Thread(target=main).start()

# returns all indices of item in seq
def listOfDupes(seq, item):
    start = -1
    locs = []
    while True:
        try:
            loc = seq.index(item, start+1)
        except:
            break
        else:
            locs.append(loc)
            start = loc
    return locs

def compute_height(node, parents):
    if node not in parents:
        return 1
    else:
        return 1 + max(compute_height(i, parents) for i in listOfDupes(parents, node))

def main():
    n = int(input())
    parents = list(map(int, input().split()))
    print(compute_height(parents.index(-1), parents))

示例输入:
    >>> 5
    >>> 4 -1 4 1 1
这将产生3的解决方案,因为根134分支1,然后是0和{ {1}}分支2,使该树的高度为4

如何在3秒的时间基准测试下改进此代码?另外,用另一种语言会更容易吗?

3 个答案:

答案 0 :(得分:2)

只要你正确算法,Python就可以了。由于您只是在寻找指导,请考虑:

1)我们知道节点的深度,如果已知父节点的深度;和 2)我们对树的结构不感兴趣,所以我们可以抛弃无关的信息。

根节点指针的值为-1。假设我们将其子节点的指针替换为值为-2的子节点,其子节点的指针为-3,依此类推。这些最大的绝对值是树的高度。

如果我们从任意节点N(0)遍历树,我们可以在节点N(k)遇到负值时立即停止,此时我们可以用其父节点的值替换每个节点,一。即,N(k-1)= N(k)-1,N(k-2)= N(k-1)-1 ... N(0)= N(1)-1。随着越来越多的指针被其深度所取代,每次遍历更有可能通过遇到深度已知的节点来终止。实际上,该算法基本上需要线性时间。

所以:将数据加载到数组中,从第一个元素开始并遍历指针,直到遇到负值。构建另一个遍历的节点数组。遇到负值时,使用第二个数组将第一个数组中的原始值替换为其深度。对第二个元素执行相同操作,依此类推。跟踪您遇到的最大深度:这是您的答案。

答案 1 :(得分:0)

这个问题的结构看起来更好地解决了自下而上而不是自上而下的问题。你自上而下的方法花费时间寻找,这是不必要的,例如:

def height(tree):
    for n in tree:
        l = 1
        while n != -1:
            l += 1
            n = tree[n]
        yield l

In []:
tree = '4 -1 4 1 1'
max(height(list(map(int, tree.split()))))

Out[]:
3

或者如果你不喜欢发电机:

def height(tree):
    d = [1]*len(tree)
    for i, n in enumerate(tree):
        while n != -1:
            d[i] += 1
            n = tree[n]
    return max(d)

In []:
tree = '4 -1 4 1 1'
height(list(map(int, tree.split())))

Out[]:
3

以上是蛮力,因为它没有利用你已经访问过的树的部分重用,添加它不应该太难。

答案 2 :(得分:0)

您的算法花费批次时间在输入中搜索数字位置。如果您只是迭代输入一次,您可以在遇到它们时记录每个数字的位置,这样您就不必在以后一遍又一遍地搜索。考虑哪种数据结构可以有效记录这些信息。