在破解编码访谈中,有一个例子,其中对二进制搜索树中的节点进行计数的递归算法的运行时为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)
答案 0 :(得分:1)
假设logN为log 2 N
这一行:
Let P = 2^(logN).
假设P
等于2^(logN)
。您还不知道N,您只需定义P
和N
之间的关系。
稍后,您可以将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
,如下所示:
其中ln(x)
是自然对数(使用基数e
)。同样,可以按如下方式重写2^x
:
然后我们可以按如下方式重写原始的order-expression:
可以简化为:
因此,如果我们的对数的基数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时产生的图:
与对数基数为10时的图形非常不同:
答案 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,但在复杂性方面它确实如此。