如何以比 O(n^2) 更快的速度从节点列表更新树?
给定:N
节点列表。每个节点由 2 个数字组成:nodeID
和 parentID
。 parentID
可能为 null
(如果它是根节点)。
是否有一种算法可以从这个节点列表中重新创建一棵树,其时间复杂度优于 O(N^2)?
每个节点可以有 0 个或多个子节点。
O(N^2) 复杂度算法的简短描述:
find a root Node, put it to a Queue
while Queue is not empty
parentNode = Queue.pop()
loop through nodes
if currentNode.parentId = parentNode.id
parentNode.addChild(currentNode)
queue.push(currentNode)
nodes.remove(currentNode)
看起来这个算法有 O(N^2) 时间复杂度(系数很小,可能是 0.25)。但我在这里的复杂度计算可能是错误的。
Given: list of N
nodes. Each node consists of 2 numbers: nodeID
and parentID
. parentID
may be null
(if it's a root node).
Is there an algorithm for recreating a tree from this list of nodes with time complexity better than O(N^2)?
Each node may have 0 or more children.
Short description of an algorithm with O(N^2) complexity:
find a root Node, put it to a Queue
while Queue is not empty
parentNode = Queue.pop()
loop through nodes
if currentNode.parentId = parentNode.id
parentNode.addChild(currentNode)
queue.push(currentNode)
nodes.remove(currentNode)
It seems that this algorithm has O(N^2) time complexity (with small coefficient, maybe 0.25). But I may be wrong at complexity calculation here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于您已经有了树的外部结构(队列),因此我假设您不介意使用一点额外的内存来更快地完成工作。
使用哈希表分两个概念步骤完成此操作:
更编程化:
这种技术的唯一潜在问题是,直到最后你不一定会得到一棵有效的树。 (也就是说,根节点在最后一个链接之前可能没有子节点。)根据您对树所做的操作,这可能是一个问题。
如果这是一个问题,您最终可以对不存在该问题的数据结构(只是没有附加数据的普通树)执行相同的操作,然后镜像该结构。
总而言之,平均起来应该是
O(N)
。Since you've already got an external structure to the tree (a queue), I'm going to assume you don't mind using a bit of extra memory to get the job done faster.
Do it in two conceptual steps with a hash table:
More programatically:
The only potential issue with this technique is you don't necessarily end up with a valid tree until the very end. (That is, the root node may not have a child until the last link.) Depending on what you're doing with your tree, this may be an issue.
If that is an issue you can end up doing the same operation with a data structure that doesn't have that issue (just a vanilla tree with no attached data) and then mirror the structure.
All in all, this should be
O(N)
on the average.对于每个节点初始化一个子节点列表,并为每个节点更新父节点的子节点列表。复杂度 O(n)。
如果父链接不易获得,则创建哈希映射。 FWIW,对于每次插入或查找,哈希映射的最坏情况复杂度是 O(logn)。所以最终的复杂度就变成了O(nlogn)。
For each node initialize a list of children and for each node update the parent's children list with itself. Complexity O(n).
If the parent link is not readily available, then create a hash map. FWIW, the best worst case complexity of hash mapping is O(logn) for each insertion or lookup. So the final complexity becomes O(nlogn).
我不知道您的输入是什么,但我们假设它是某种无序列表。
然后,您可以通过将它们放入允许通过其 nodeID 查找的数据结构中来创建树结构。例如,数组就可以做到这一点。然后你就有了一棵只在父母的方向上链接的树。假设节点 ID 是唯一的,则可以在线性时间内从无序列表转换为该数组。
为了使树也沿着子节点的方向链接,您可以使用数据结构(例如列表)准备节点来保存子节点,然后执行第二遍将每个节点添加到其父节点的子节点列表中。这在线性时间内也是可能的。
I do not know what your input is, but let's assume that it is some sort of unordered list.
You can then create a tree structure by just putting them into a data structure that allows looking them up by their nodeID. For example, an array would do that. You then have a tree that is only linked in the direction of the parents. Transformation from an unordered list into this array is possible in linear time, assuming that the nodeIDs are unique.
In order to get the tree also linked in the direction of the children, you can prepare the nodes with a data structure (e.g. a list) to hold the children, and then do a second pass that adds each node to its parent's children list. This is also possible in linear time.