如何简化O(2 ^(logN))到O(N)

时间:2018-05-07 04:11:28

标签: runtime time-complexity

在破解编码访谈中,有一个例子,其中对二进制搜索树中的节点进行计数的递归算法的运行时为O(2 ^(logN))。这本书解释了我们如何简化以获得O(N)......

2^p = Q 
logQ = P 
Let P = 2^(logN).

但是当他们说Let P = 2 ^(logN)时,我迷失了。我不明白我们怎么知道将这两者相等,我也不明白这一步......(虽然他们告诉我他们是按照log base 2的定义来做的)

logP = logN 
P = N 
2^(logN) = N

因此代码的运行时间为O(N)

3 个答案:

答案 0 :(得分:1)

假设logN为log 2 N

这一行:

Let P = 2^(logN).

假设P等于2^(logN)。您还不知道N,您只需定义PN之间的关系。

稍后,您可以将log函数应用于等式的两边。由于log(2^(logN))logN,因此下一步是:

logP = logN

显然,当logP = logN时,那么:

P = N

以前你假设P = 2^(logN),然后:

2^(logN) = N

此外,根据2^logN = N函数的定义,所有这些都可以简化为log

答案 1 :(得分:0)

简短的回答是,原始问题可能隐含地假设对数应该在基数2中,因此2 ^(log_2(N))只是N,通过定义log_2(x)作为反函数2 ^ y。

然而,如果对数是针对不同的基数,那么更仔细地检查这一点很有意思。标准结果允许我们将对数写入基数b,如下所示:

enter image description here

其中ln(x)是自然对数(使用基数e)。同样,可以按如下方式重写2^x

enter image description here

然后我们可以按如下方式重写原始的order-expression:

enter image description here

可以简化为:

enter image description here

因此,如果我们的对数的基数b是2,那么这显然只是N。但是,如果基数不同,那么我们会将N提升到一个权力。例如,如果b=10我们将N提升到0.301的幂,这肯定是一个比O(N)更缓慢增加的函数。

我们可以使用以下Python脚本直接检查:

import numpy
import matplotlib.pyplot as plt

N = numpy.arange(1, 100)

plt.figure()
plt.plot(N, 2**(numpy.log2(N)))
plt.xlabel('N')
plt.ylabel(r'$2^{\log_2 N}$')

plt.figure()
plt.plot(N, 2**(numpy.log10(N)))
plt.xlabel('N')
plt.ylabel(r'$2^{\log_{10} N}$')

plt.show()

当我们假设对数是基于2时产生的图:

enter image description here

与对数基数为10时的图形非常不同:

enter image description here

答案 2 :(得分:-1)

对数的定义是“为了得到这个值,需要提高基数的功率”,所以如果对数的基数是2,那么将2提高到该功率会使我们达到原始值。

示例:N是256.如果我们得到它的基数为2的对数,我们得到8.如果我们将2加到8的幂,我们得到256.所以它是线性的,我们可以使它只是N. / p>

如果日志位于不同的基数中,例如10,那么转换只需要将指数除以常量,将更准确的表单转换为N = 2^(log N / log 2),可以将其更改为N / 2^(1 / log 2) = 2^log N }。这里左边N的除法器是一个常数,所以我们在讨论复杂性时可以忘记它,然后再来N = 2^log N

您也可以手动测试。 256的Log2为8. 128的Log2为7. 8/7约为1.14。 256的Log10是2.4。 128的Log10是2.1。 2.4 / 2.1约为1.14。所以基数并不重要,你得到的价值不一样,但它是线性的。所以在数学上N不等于2 ^ Log10 N,但在复杂性方面它确实如此。