如何计算二分搜索的复杂度


Answers:


385

尽管不是很复杂,但这里是一种更数学的观察方法。IMO比非正式的更为清晰:

问题是,您可以将N除以2多少次,直到得到1?本质上就是说,进行二进制搜索(将元素减半),直到找到它为止。用公式可以是:

1 = N / 2 x

乘以2 x

2 x = N

现在执行日志2

对数2(2 x)=对数2 N
x *对数2(2)=对数2 N
x * 1 =对数2 N

这意味着您可以将日志除以N次,直到将所有内容都除。这意味着您必须除以log N(“执行二进制搜索步骤”),直到找到您的元素。


我只是将其计算为t(n)=(2 ^ 2)* K。如何使其成为日志表格?
山汗

1
相同的概念以图形方式进行了解释:stackoverflow.com/a/13093274/550393
2cupsOfTech

我缺少的部分是,如果您有一个包含7个条目的BST,它的公式是什么?log2(7)?我对所有可能的结果都进行了蛮力计算,得出的答案不等于log2(7),那么我在做什么错呢?
佩里·蒙绍

1
比二叉树解释容易得多。
NoName

1
非常好的答案
VHS

22

对于二分查找,T(N)= T(N / 2)+ O(1)//递归关系

应用Masters定理计算递归关系的运行时复杂度:T(N)= aT(N / b)+ f(N)

在这里,a = 1,b = 2 => log(a b)= 1

同样,在这里f(N)= n ^ c log ^ k(n)// k = 0&c = log(以b为底)

因此,T(N)= O(N ^ c log ^(k + 1)N)= O(log(N))

资料来源:http : //en.wikipedia.org/wiki/Master_theorem


1
为什么当a = 1和b = 2时log(a的基数b)为1,不应该为0吗?
良维亚

16

T(n)= T(n / 2)+1

T(n / 2)= T(n / 4)+ 1 + 1

将The(n / 2)的值放在上面,这样T(n)= T(n / 4)+ 1 + 1。。。。T(n / 2 ^ k)+ 1 + 1 + 1 ..... + 1

= T(2 ^ k / 2 ^ k)+ 1 + 1 .... + 1至k

= T(1)+ k

当我们取2 ^ k = n

K =对数n

因此时间复杂度为O(log n)


10

它的搜索时间不是一半,也不会使它成为log(n)。它以对数形式减少。对此稍加思考。如果表中有128个条目,并且必须线性搜索您的值,那么平均大约需要64个条目才能找到您的值。那是n / 2或线性时间。使用二进制搜索时,您每次迭代都消除了1/2可能的条目,这样最多只需要7个比较就可以找到您的值(对数基数2的128为7或2乘以7的幂为128)。二进制搜索的力量。


对不起,死灵柱了,但是128棵树还没装好。我使用一个基本示例来解决这个问题,发现7个条目均匀地填充了3层的树。我计算出复杂度应为17/7(比较总和的平均值),即2.43。但是log2(7)是2.81。那我在这里想念什么?
佩里·蒙绍

两个答案-第一个答案:即使数学上没有错误,我们也可以看到线性的2.43平均值仍然好于3.5平均值,而且平均值较低。一旦进入100项,log2()就会比线性好得多。我认为您虽然看到了,所以接下来。
Michael Dorgan

1
第二个答案:我不确定您拥有的那棵树,其中7填满了所有东西。当我想到由8个条目组成的完美树时,我看到一个3层深的树,总共有8个叶子。在这棵树中,无论您搜索哪个数字,从根到叶总共需要进行3次比较。对于7个条目,一条路径的比较少一,因此20/7(3个比较的6个节点,2个比较的1个节点)约为2.85。Log2(7)为〜2.81。我没有数学背景来解释.04的差异,但是我想这与没有可用的小数位或其他魔术有关:)
Michael Dorgan

多少就是叶子的数量!?不是节点数?好吧,那是我丢失的一大条信息。对于每个分支节点也是一个潜在的停止点,该功能似乎基于叶子,这令我感到奇怪。好吧,谢谢您为我解决问题!
佩里·蒙绍

5

二进制搜索算法的时间复杂度属于O(log n)类。这称为大O表示法。您应该这样解释:给定大小为n的输入集,函数执行所需时间的渐近增长不会超过log n

这只是形式数学术语,以便能够证明语句等。它具有非常简单的解释。当n变得非常大时,log n函数将超出执行该函数所需的时间。“输入集”的大小n仅是列表的长度。

简而言之,二进制搜索出现在O(log n)中的原因是它在每次迭代中将输入集减半。在相反的情况下考虑起来更容易。在x迭代中,最大的二进制搜索算法可以检查多长时间的列表?答案是2 ^ x。由此可见,相反的是,对于长度为n的列表,二进制搜索算法平均需要log2 n次迭代。

如果它为什么是O(log n)而不是O(log2 n),那是因为再说一次-使用大的O表示法常数不计算在内。


4

这是维基百科条目

如果您看一下简单的迭代方法。您只是消除了要搜索的元素的一半,直到找到所需的元素。

这是我们如何得出公式的解释。

首先说您有N个元素,然后首先尝试⌊N/2⌋。其中N是下限和上限之和。N的第一个时间值将等于(L + H),其中L是要搜索的列表的第一个索引(0),H是最后一个索引。如果幸运的话,您尝试找到的元素将位于中间[例如,您正在列表{16,17,18,19,20}中搜索18,然后计算⌊(0 + 4)/2⌋= 2,其中0是下限(L-数组第一个元素的索引) 4是上限(H-数组最后一个元素的索引)。在上述情况下,L = 0和H =4。现在2是要搜索的元素18的索引。答对了!您找到了。

如果案例是一个不同的数组{15,16,17,18,19},但您仍在搜索18,那么您将不会很幸运,并且您将首先执行N / 2(即⌊(0 + 4)/ 2⌋= 2,然后发现索引2处的元素17并不是您要查找的数字。现在您知道,在下一次尝试搜索迭代方式时,不必查找数组的至少一半。因此,基本上,您不会在每次尝试查找先前尝试中找不到的元素时都搜索先前搜索的元素列表的一半。

所以最坏的情况是

[N] / 2 + [(N / 2)] / 2 + [((N / 2)/ 2)] / 2 .....
即:
N / 2 1 + N / 2 2 + N / 2 3 + ..... + N / 2 x …..

直到…完成搜索,您要查找的元素在列表的末尾。

这表明最坏的情况是当您达到N / 2 x时x 等于2 x = N

在其他情况下,N / 2 x ,其中x使得2 x <N x的最小值可以为1,这是最佳情况。

现在由于数学上最坏的情况是
2 x = N
=> log 2(2 x)= log 2(N)
=> x * log 2(2)= log 2(N)
=> x * 1 = log的值2(N)
=>更正式⌊log 2(N)+1⌋


1
您究竟如何获得更正式的版本?
Kalle

使用发言权功能。详细信息在答案中提供的Wiki链接的性能部分(en.wikipedia.org/wiki/Binary_search_algorithm)中。
RajKon


2

假设二进制搜索的迭代在k次迭代后终止。在每次迭代时,数组将被除以一半。假设任何迭代的数组长度为n在迭代1时

Length of array = n

在迭代2中,

Length of array = n⁄2

在迭代3中,

Length of array = (n⁄2)⁄2 = n⁄22

因此,在迭代k之后,

Length of array = n⁄2k

另外,我们知道,ķ分裂后之后,该阵列的长度变为1 因此

Length of array = n⁄2k = 1
=> n = 2k

双方都应用日志功能:

=> log2 (n) = log2 (2k)
=> log2 (n) = k log2 (2)
As (loga (a) = 1)

因此,

As (loga (a) = 1)
k = log2 (n)

因此,二分搜索的时间复杂度为

log2 (n)

1

二进制搜索的工作原理是将问题反复分成两半,如下所示(详细信息省略):

在[4,1,3,8,5]中寻找3的示例

  1. 订购物品清单[1,3,4,5,8]
  2. 看中间项目(4),
    • 如果这是您想要的,请停止
    • 如果更大,请看前半部分
    • 如果少于一半,请看下半部分
  3. 对新列表[1,3]重复步骤2,找到3并停止

这是一个双向 -nary搜索,当你在2分割的问题。

搜索仅需要log2(n)步骤即可找到正确的值。

如果您想了解算法的复杂性,我会推荐算法入门


1

由于我们每次都会将列表切成两半,因此我们只需要知道在将列表除以2的多少步就可以得到1。在给定的计算中,x表示划分列表直到得到一个元素的时间(最坏的情况)。

1 = N / 2x

2倍= N

以log2

log2(2x)= log2(N)

x * log2(2)= log2(N)

x = log2(N)


1

T(N)= T(N / 2)+ 1

T(N)= T(N / 2)+1 =(T(N / 4)+1)+1

...

T(N)= T(N / N)+(1 +1 +1 + ... + 1)= 1 + logN(以2为底的对数)= 1 + logN

因此二进制搜索的时间复杂度为O(logN)


0
ok see this
for(i=0;i<n;n=n/2)
{
i++;
}
1. Suppose at i=k the loop terminate. i.e. the loop execute k times.

2. at each iteration n is divided by half.

2.a n=n/2                   .... AT I=1
2.b n=(n/2)/2=n/(2^2)
2.c n=((n/2)/2)/2=n/(2^3)....... aT I=3
2.d n=(((n/2)/2)/2)/2=n/(2^4)

So at i=k , n=1 which is obtain by dividing n  2^k times
n=2^k
1=n/2^k 
k=log(N)  //base 2

0

让我举个例子让大家都容易。

为了简单起见,我们假设数组中有32个元素按排序顺序进行排序,我们将使用二进制搜索从中搜索元素。

1 2 3 4 5 6 ... 32

假设我们正在搜索32。在第一次迭代之后,我们将剩下

17 18 19 20 .... 32

在第二次迭代之后,我们将剩下

25 26 27 28 .... 32

在第三次迭代之后,我们将剩下

29 30 31 32

在第四次迭代之后,我们将剩下

31 32

在第五次迭代中,我们将找到值32。

因此,如果将其转换为数学方程式,我们将得到

(32 X(1/2 5))= 1

=> n X(2 -k)= 1

=>(2 k)= n

=> k对数2 2 =对数2 n

=> k =对数2 n

因此证明。


0

这是使用主定理和可读LaTeX的解决方案。

对于二进制搜索的递归关系中的每个递归,我们将问题转换为一个子问题,运行时间为T(N / 2)。因此:

T(n)= T(n / 2)+1

代入主定理,我们得到:

T(n)= aT(n / b)+ f(n)

现在,因为洛格巴是0,而f(n)是1,我们可以使用主定理的第二种情况,因为:

f(n)= O(1)= O(n0)= O(nlogba)

这意味着:

T(n)= O(nlogbalogn)= O(n0logn)= O(logn)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.