这个计算 a^n 的算法是如何被重写以在 O(log n) 时间内运行的?

Posted

技术标签:

【中文标题】这个计算 a^n 的算法是如何被重写以在 O(log n) 时间内运行的?【英文标题】:How did this algorithm for computing a^n get rewritten to run in O(log n) time? 【发布时间】:2013-10-07 06:15:02 【问题描述】:

假设你想计算一个n。一个简单的算法会将a、n乘以如下:

result = 1;
for(int i =1; i <= n; i++)
    result *= a; 

该算法需要 O(n) 时间。不失一般性,假设n=2^k

您可以使用以下方案改进算法:

 result = a;
 for (int i = 1; i <= k; i++)
     result = result * result; 

该算法需要 O(log n) 时间。对于任意的n,可以修改算法,证明复杂度还是O(logn)

好糊涂,那n=2k怎么算,为什么第二个例子中只显示了k?不明白这如何转化为 O(logn) 时间复杂度...

【问题讨论】:

拜托,您能否在一开始就说明该算法试图解决的问题是什么?这听起来很像家庭作业…… 这可能有助于理解您正在考虑一种特殊情况,其中 n 是 2 的幂。在这种特殊情况下,您可以更有效地实施例程。 @nyarlathotep 不是家庭作业,而是教科书中的一个例子,没有解释为什么会这样。 不失一般性,假设 n=2^k。 这是很多失一般性。 【参考方案1】:

第二种算法在一般情况下不起作用;它仅在存在一些 k 以便您可以编写 n = 2k 时才有效。如果有 k 可以做到这一点,那么通过取等式两边的对数,你会得到 log2 n = k。因此:

循环计数为 k,运行 O(log n) 次。 因此,循环运行时间为 O(log n)。

如果你想摆脱神秘的k,你可以写

int result = a;
for (int i = 0; i < log2(n); i++) 
    result = result * result;

这更清楚地在 O(log n) 时间内运行,因为循环运行 log2 n 次,并且每次迭代都运行 O(1)。

我认为“不失一般性”说 n 是 2 的完美幂是不公平的,因为并非所有数字都是!上面的代码只有在 n 是 2 的幂时才有效。您可以使用 repeated squaring algorithm 将其推广到非二次幂,它具有 O(log n) 复杂度但适用于任何幂。

希望这会有所帮助!

【讨论】:

@templatetyedef 很棒的答案!谢谢你这么清楚!!我不知道为什么教科书对初学者来说不能更明确一点!再次感谢!

以上是关于这个计算 a^n 的算法是如何被重写以在 O(log n) 时间内运行的?的主要内容,如果未能解决你的问题,请参考以下文章

O(n)是啥

如何计算大O? [关闭]

AcWing第2场热身赛-2021/5/29

什么会导致算法具有 O(log n) 复杂度?

如何在时间复杂度为大O(N)的循环内对数组部分求和

如何找到当前 url 被重写?