这个递归算法的大O
我做了以下涉及二叉堆结构的算法:
Algorithm: heapMinimum(node)
Input : Position n
Output : Sequence minList; containing the postions that hold the minimum value
1. minList <-- sequence
2. if parent(node) == NULL // current node is the root of the tree
3. minList.insertLast(node)
4. if (leftchild(node).element() == node.element())
5. concat(heapMinimum(leftchild(node), minList))
6. if(right(node).element() == node.element())
7. concat(heapMinimum(rightChild(node), minList))
8. return minList
该算法所做的基本上是遍历给定根的二叉堆,以查找并存储保存最小值(即与根的值匹配的值)的节点。
现在我在计算算法的运行时间(以大 O 表示法)时遇到困难。我感到困惑的原因是因为用于遍历每个节点的左子节点和右子节点的递归。
所有操作都在常数时间内运行,O(1)
(concat
除外)。但是我到底该如何计算这种递归解决方案的运行时间呢?
I did the following algorithm involving a Binary Heap structure:
Algorithm: heapMinimum(node)
Input : Position n
Output : Sequence minList; containing the postions that hold the minimum value
1. minList <-- sequence
2. if parent(node) == NULL // current node is the root of the tree
3. minList.insertLast(node)
4. if (leftchild(node).element() == node.element())
5. concat(heapMinimum(leftchild(node), minList))
6. if(right(node).element() == node.element())
7. concat(heapMinimum(rightChild(node), minList))
8. return minList
What the algorithm does is basically traverse a Binary Heap given its root to find and store the nodes that hold the minimum value (ie the value that matches that of the root).
Now I'm having trouble calculating the running time, in Big O notation, of my algorithm. The reason I'm getting confused is because of the recursion that is used to traverse the left and right children of each node.
All of the operations run in constant time, O(1)
, except concat
. But how do I exactly go about in calculating the running time of such a recursive solution ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对我来说看起来像 O(N),其中 N 是元素的数量。如果堆只包含相等的元素,则将遍历所有元素。另外,为什么 concat 不是 O(1) ?只要你“连接”数字,它也应该是 O(1)。如果不知何故 concat 是 O(N) 但是(从你的伪代码看来是这样 - 但你应该重新考虑是否真的需要连接两个返回的列表),那么总时间将是 O(N2)最坏的情况。
Looks like O(N) to me, where N is the number of elements. If your heap contains nothing but equal elements, all the elements will be traversed. Also, why isn't concat O(1)? As long as you are "concatenating" numbers, it should also be O(1). If somehow concat is O(N) however (from your pseudocode it looks like it is - but you should reconsider if you really need to concatenate the two returned lists), then the total time would be O(N2) worst case.
我假设您正在谈论二进制堆?
根据堆属性的定义,您应该只递归直到找到大于根的元素。但是,您还必须确保当前级别的树中没有任何其他元素与根的大小相同。本质上,这产生了这样的规则:一旦遇到堆中大于根的元素,就不需要递归到该元素的子元素。
然而,在最坏的情况下,每个元素可能等于根。在这种情况下,您必须检查整个堆,这会产生 O(n) 时间,其中 n 是堆中元素的数量。
所以回答你的问题,它是 O(n)
I assume you are talking about a binary heap?
By definition of the heap properties, you should only be recursing until you find an element larger than what the root is. However, you must also be certain that none of the other elements at the current level of the tree are the same size as the root. Essentially, this yields the rule that once you encounter an element of the heap that is greater than the root, you do not need to recurse into the element's children.
However, in the worst case, each element may be equal to the root. In this case, you must check the entire heap, which yields O(n) time, where n is the number of elements in the heap.
So to answer your question, it is O(n)
正如其他人提到的,如果你的 concat() 是 O(1) [如果不是,你可以这样做],那么你的算法的输出大小是 O(N) 。
但是,如果您使用 concat() 来复制列表(取决于系统,这可能很容易意外执行),那么最坏的情况是输出大小为 O(N^2)。导致此行为的一种情况是当您的最小节点深入到树中时,这样您的 concat() 就会在每个级别不断复制列表。
请注意,此深度受到堆深度的限制,因此如果您的树是平衡的,则这种最坏情况的数据结构大小也是 O(M log M)。您可以看到这一点,因为最大副本数就是树的深度。
As others have mentioned, if your concat() is O(1) [and if it's not, you can make it so] then your algorithm is O(N) in the size of the output.
However, if you used a concat() that copies your list (depending on the system, this can be easy to accidentally do), then your worst case is O(N^2) in the size of the output. A case that causes this behavior is when your minimum nodes go deep into the tree, such that your concat() keeps copying the list at each level.
Note that this depth is bounded by the depth of your heap, so if your tree is balanced, this worst case is also O(M log M) in the size of the datastructure. You can see this because the maximum number of copies is the depth of the tree.
我想你的解决方案中有一个错误。
第一次检查:
,但必须添加 node != NULL 的检查。
此外,我建议使用 list 作为附加参数,您将在其中放置答案。
这就是我的实现:
假设向列表添加一个元素需要 O(1),我们得到该函数需要 O(k),其中 k 是堆中最小值的数量。
享受。
I suppose you have a bug in your solution.
The first check:
must be removed, but the check that node != NULL must be added.
Moreover, I suggest to use list as additional parameter, where you will put the answer.
So, that is my implementation:
Assuming that adding an element to the list take O(1), we get that the function takes O(k), where k is the number of minimal values in the heap.
Enjoy.