【发布时间】:2012-01-01 08:58:31
【问题描述】:
我听说有人说,由于二进制搜索将搜索所需的输入减半,因此它是 log(n) 算法。由于我不是数学背景,我无法与之相关。有人可以更详细地解释一下吗?是不是跟对数级数有关系?
【问题讨论】:
-
这可能对你有帮助:stackoverflow.com/a/13093274/550393
标签: algorithm search time-complexity binary-search
我听说有人说,由于二进制搜索将搜索所需的输入减半,因此它是 log(n) 算法。由于我不是数学背景,我无法与之相关。有人可以更详细地解释一下吗?是不是跟对数级数有关系?
【问题讨论】:
标签: algorithm search time-complexity binary-search
⌊log₂(n) + 1⌋ 是在二分搜索中找到某物所需的最大比较次数。平均情况大约进行 log2(n) - 1 比较。这里有更多信息:
【讨论】:
它没有一半的搜索时间,这不会使它成为 log(n)。它以对数方式减小它。对此稍加思考。如果您在一个表中有 128 个条目并且必须线性搜索您的值,那么平均可能需要大约 64 个条目才能找到您的值。那是 n/2 或线性时间。使用二分搜索,您可以在每次迭代中消除 1/2 的可能条目,这样最多只需进行 7 次比较即可找到您的值(128 的以 2 为底的对数为 7 或 2 的 7 次方为 128。)这是二分查找的威力。
【讨论】:
二分搜索的工作原理是将问题反复分成两半,如下所示(细节省略):
在 [4,1,3,8,5] 中查找 3 的示例
当您将问题划分为 2 时,这是一个 bi-nary 搜索。
搜索只需要 log2(n) 个步骤即可找到正确的值。
如果您想了解算法复杂性,我会推荐 Introduction to Algorithms。
【讨论】:
二分查找算法的时间复杂度属于O(log n)类。这称为big O notation。您应该解释这一点的方式是,在给定大小为 n 的输入集的情况下,函数执行时间的渐近增长不会超过 log n。
这只是正式的数学术语,以便能够证明陈述等。它有一个非常简单的解释。当 n 变得非常大时,log n 函数将超过执行该函数所需的时间。 “输入集”的大小 n 就是列表的长度。
简单地说,二分搜索在 O(log n) 中的原因是它在每次迭代中将输入集减半。在相反的情况下更容易考虑它。在 x 次迭代中,二分搜索算法最多可以检查多长的列表?答案是 2^x。从这里我们可以看到相反的是,对于长度为 n 的列表,二分搜索算法平均需要 log2 n 次迭代。
如果为什么它是 O(log n) 而不是 O(log2 n),那是因为简单地再放一遍 - 使用大 O 符号常量不算数。
【讨论】:
这里有一种更数学的方式来看待它,虽然不是很复杂。 IMO 比非正式的更清晰:
问题是,你可以将 N 除以 2 多少次才能得到 1?这本质上是说,进行二分搜索(一半的元素),直到找到它。在公式中是这样的:
1 = N / 2x
乘以 2x:
2x = N
现在做日志2:
log2(2x) = log2 N
x * log2(2) = log2 N
x * 1 = log2 N
这意味着您可以将 log N 次划分,直到所有内容都划分完毕。这意味着您必须除以 log N(“执行二进制搜索步骤”),直到找到您的元素。
【讨论】:
对于二分搜索, T(N) = T(N/2) + O(1) // 递归关系
应用大师定理计算递归关系的运行时间复杂度: T(N) = aT(N/b) + f(N)
这里,a = 1,b = 2 => log (a base b) = 1
同样,这里 f(N) = n^c log^k(n) //k = 0 & c = log (a base b)
所以,T(N) = O(N^c log^(k+1)N) = O(log(N))
【讨论】:
这里是wikipedia 条目
如果您看一下简单的迭代方法。您只是消除了一半要搜索的元素,直到找到所需的元素。
这是我们如何得出公式的说明。
假设最初你有 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/21 + N/22 + N/23 +..... + N/2x .....
直到……您完成搜索,您要查找的元素在列表末尾的位置。
这表明最坏的情况是当您达到 N/2x 时,x 等于 2x = N
在其他情况下 N/2x 其中 x 满足 2x
现在因为数学上最坏的情况是
2x = N
=> log2(2x) = log2(N)
=> x * log2(2) = log2(N)
=> x * 1 = log2(N)
=> 更正式的⌊log2(N)+1⌋
【讨论】:
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 = log n
所以时间复杂度是 O(log n)
【讨论】:
由于我们每次将列表减半,因此我们只需要知道在继续将列表除以 2 时得到 1 的步数。在下面给定的计算中,x 表示我们划分一个列表直到我们得到一个元素的时间(在最坏情况下)。
1 = N/2x
2x = N
取log2
log2(2x) = log2(N)
x*log2(2) = log2(N)
x = log2(N)
【讨论】:
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
【讨论】:
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 (base 2 log) = 1 + logN
所以二分查找的时间复杂度是O(logN)
【讨论】:
让我举个例子让大家容易理解。
为简单起见,我们假设数组中有 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/25)) = 1
=> n X (2-k) = 1
=> (2k) = n
=> k log22 = log2n
=> k = log2n
因此证明。
【讨论】:
假设二分搜索中的迭代在 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
另外,我们知道之后 k次分割后,数组的长度变为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)
【讨论】: