【问题标题】:How to determine the time complexity of this algorithm?如何确定该算法的时间复杂度?
【发布时间】:2015-08-08 12:23:15
【问题描述】:

以下函数计算 a^b。 假设我们已经有一个 prime_list 包含所有需要的素数并且从小到大排序。 代码是用python写的。

def power(a,b):
    if b == 0:
        return 1

    prime_range = int(sqrt(b)) + 1
    for prime in prime_list:
        if prime > prime_range:
            break
        if b % prime == 0:
            return power(power(a, prime), b/prime)

    return a * power(a, b-1)

如何确定它的时间复杂度? p.s.代码并不完美,但正如您所见,这个想法是使用素数来减少算术运算的次数。 我仍在寻找一个理想的实现,所以如果你想出一些东西,请帮忙。谢谢!

【问题讨论】:

  • 您使用什么语言?您可以以编程方式测量运行时间。
  • 即使您的语言的 sqrt() 也是基于实现的。除非您提供所需的详细信息,否则无法找到此功能的整体复杂性。
  • 您真的要测量时间复杂度吗?反对“如何确定时间复杂度”或“如何测量运行时间”?
  • 您使用的语言似乎是 Python。所描述的算法具有 O(n) 复杂度。但是,要测量时间运行时间,您可以导入 timeit,正如您在 stackoverflow.com/questions/2662140/… 中看到的那样。
  • @Stef 对不起英语不好:-(

标签: algorithm time-complexity number-theory


【解决方案1】:

for 循环耗尽时的最坏情况。但在这种情况下,b 在下一次递归调用中被 2 除。

在最坏的情况下,我们在每一步的大约 sqrt(b) 操作中将 b 除以 2,直到 b 达到 1。
所以如果我们设置方程

f(1) = 1 和 f(n) = f(n/2) + sqrt(n)

我们得到using woflram alpha

f(n) = (1+sqrt(2)) (sqrt(2) sqrt(n)-1)
那是
O(sqrt(b))

【讨论】:

  • 如果你想要递归的实际证明(没有 wolfram alpha),你只需要sqrt(n) + sqrt(n/2) + sqrt(n/4) + sqrt(n/(2^log2(n)))(因为2^log2(n) = 1),它就是sqrt(n) * sum((1/sqrt(2))^I)I = 1..log2(n),使用公式对于几何系列的总和,您会得到所需的答案;)
  • 如果b 是素数,它不会被2整除。
  • @Juan Lopes 如果 b 是素数,则第一个循环将被耗尽(有条件检查素数
  • @LukaRahne 我认为您的算法可以很好地近似平均情况,但最坏的情况是其他情况:您需要找到f,例如f(2p+1) = f(2p) + sqrt(2p+1)f(2p) = f(p) + sqrt(2p),这个如果你有一个素数 b 会发生,其中(b - 1) / 2 也是素数(依此类推,直到你达到 1),我不知道这样的数字是否存在,但这可能会发生(23 几乎有这个属性,因为你得到23 -> 22 -> 11 -> 10 -> 5 -> 4 -> 2 -> 1) ;)
  • @LukaRahne 我明白了,但是如果我们有一个 2^k-1 形式的数字,它将有 O(k) 次循环必须耗尽。 (例如 31->30->15->14->7->6->3->2->1->0)。在这种情况下,将有 O(log(n) * sqrt(n)) 操作。
猜你喜欢
  • 1970-01-01
  • 2018-01-11
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
相关资源
最近更新 更多