【问题标题】:What is the big-Oh runtime of two recursive O(logn) calls?两个递归 O(logn) 调用的大 O 运行时是多少?
【发布时间】:2014-04-22 22:57:44
【问题描述】:
def f(L):
    if len(L) < 1 billion:
        return L
    else:
        return f(L[:len(L) // 2]) + f(L[len(L) // 2:])

L 是大小为 n 的列表

我知道如果是单次递归调用,那就是O(logn),但是这里有两次递归调用。

但是当我开始在可视化器上运行它时,它开始表现出更多的 O(n) 运行时间。

在我看来,它应该是 O(logn+logn) = O(2logn) = O(logn)。我说的对吗?

【问题讨论】:

  • L是什么对象?
  • 这只是一个列表。我会把它放在那里。
  • 顺便说一句,使用 memoize 装饰器应该会快一些。

标签: python recursion big-o logarithm


【解决方案1】:

考虑一下你打了多少电话。在递归的第一级,您将进行 2 次调用。对于其中的每一个,您将再打两个电话。等等...这意味着在递归级别的i 上,您总共会进行O(2^i) 函数调用。

递归有多少级?这只是具有n 元素的二叉树的高度,即O(log_2 n)

因此,当您到达递归的所有叶子时,您将完成 O(2^(log_2 n)) = O(n) 函数调用。

--

另一种看待它的方式是,您最终必须将整个列表拼凑起来,那么您怎么可能在不到O(n) 的时间内完成呢?

【讨论】:

  • 哇,这太有帮助了!我也想知道 O(n) 是如何得出的。非常感谢!
【解决方案2】:

如果len(L) 至少为 10 亿,您的算法将是 O(n),因为您会将列表分成两部分,然后将两部分加在一起。切片和添加都是 O(n) 操作。

如果要测试两次递归调用的运行时间,

1.传入开始和结束索引,并调用

f(L, start, start+(end-start)//2) + f(L, start+(end-start)//2, end)

2.end-start 小于 10 亿时,返回 end-start 或其他 O(1) 值

【讨论】:

  • 哦,谢谢!我想我现在明白了。如果整数除以 O(logn) 会忽略列表的一半,但在这里我不会忽略我除的另一半。谢谢! (:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-14
  • 2012-08-28
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
相关资源
最近更新 更多