我有一个通用加权树(没有周期的无向图,连接),有n个节点,n-1个边连接一个节点到另一个节点。
我的算法执行以下操作:
DO
计算实际叶子(度数为1的节点)
从树中删除所有树叶和它们的边缘,标记每个父项,并使用其连接树叶的最大成本值 (例如,如果内部节点连接到带有成本为5,6的边的两个叶子,那么我们在用6除去叶子后标记内部节点)
直到树的大小<= 2
返回标有
的最高费用的节点
我可以说计算叶子的复杂度为O(n)
吗?O(n)
用叶子消除每条边缘,所以我有O(n)+O(n) = O(n)
?
答案 0 :(得分:1)
您可以在O(n)中轻松地执行此操作,其中集合实现为简单列表,队列或堆栈(处理顺序不重要)。
将所有叶子放入集合中。
在循环中,从集合中删除一个叶子,从图形中删除它的边缘。通过更新父级的最大值来处理标签。如果父级现在是叶子,则将其添加到集合中并继续运行。
当集合为空时,您已完成,节点标签正确。
最初构造集合是O(n)。每个顶点都放在集合上,删除它的标签只处理一次。这都是不变的时间。因此,对于n个节点,它是O(n)时间。所以我们有O(n)+ O(n)= O(n)。
答案 1 :(得分:0)
当然可以在O(n)
中执行此过程,但您的算法是否确实依赖。
如果“计算实际叶子”或“删除所有叶子及其边缘”循环遍及整个树,则该步骤将O(n)
。
在最坏的情况下(如果树非常不平衡),上述两个步骤将重复O(n)
次,因此,总共需要O(n2)
。
要在O(n)
中执行此操作,您可以让每个节点指向其父节点,这样您就可以在固定时间内删除叶子并保留叶子集合,这样您就可以始终拥有叶子,而不必计算它们 - 这会导致O(n)
运行时间。
答案 2 :(得分:0)
因为你的树是一个艺术树。它也可以是一个链接列表,在这种情况下,您将在每次迭代中消除一个节点,并且需要(n-2)
次迭代O(n)
来查找叶子。
所以你的算法实际上是O(N^2)
这是一个更好的算法,可以在O(N)
中为任何树
deleteLeaf(Node k) {
for each child do
value = deleteLeaf(child)
if(value>max)
max = value
delete(child)
return max
}
deleteLeaf(root) or deleteLeaf(root.child)