在O(lgn)中搜索部分排序的数组

时间:2013-07-08 21:53:51

标签: arrays algorithm search binary-search

我很难解决这个问题。

A[1..n] is an array of real numbers which is partially sorted:
There are some p,q  (1 <= p <= q <=n) so:
A[1] <= ... <= A[p]
A[p] >= ... >= A[q]
A[q] <= ... <= A[n]

How can we find a value in this array in O(lgn)?
(You can assume that the value exists in the array)

3 个答案:

答案 0 :(得分:7)

进行3次二分查找:从1到p,p到q,q到n。复杂性仍然是O(logn)。

因为我们不知道p和q:

您无法在登录时解决此问题。假设您有一个正数的排序列表,其中一个零混合(p + 1 = q和A [q] = 0)。这种情况符合您提到的所有标准。现在,找到零所在位置的问题不能在子O(n)时间内解决。因此,在O(logn)时间内无法解决您的问题。

答案 1 :(得分:0)

尽管已经指出了“隐藏零”的最坏情况,我仍然建议实施一种通常可以加快速度的算法,具体取决于p,q。例如,假设您有n个数字,并且每个增加和减少的区域的大小至少为k。然后,如果检查数组中的2 ^ m个元素,包括第一个和最后一个元素,其余元素尽可能等间距,从m = 2开始,然后迭代地将m增加1,最终你将达到m从你检查过的2 ^ m个元素中,从左到右找到3对连续元素(A,B),(C,D),(E,F),它们满足A&lt; B,C> D,E&lt; F(一些对可能共享元素)。如果我的背包计算是正确的,那么你需要实现这一点的最坏情况是你要检查不超过4n / k个元素,所以例如如果k = 100,则比检查所有n个元素要快得多。然后你知道A之前的所有事情,F之后的所有事情都在增加序列,你可以通过二进制搜索它们。现在,如果m足够大,你至少检查了sqrt(n)元素,那么你可以通过在A和F之间进行强力搜索来完成,整个运行时间将为O(n / k + sqrt(n) ))。另一方面,如果最终m检查的元素少于sqrt(n),则可以进一步增加m,直到检查了sqrt(n)元素。然后将有2对连续的检查元素(A,B),(C,D)满足A&lt; B,C> D,并且在阵列中稍后还将有2对连续的检查元素(W,X),(Y,Z)满足W&gt; X,Y < Z.然后A之前的一切都在增加,D和W之间的一切都在减少,而Z之后的一切都在增加。因此,您可以二进制搜索阵列中的这3个区域。您尚未完全搜索的数组的剩余部分的大小为O(sqrt(n)),因此您可以使用强制搜索未选中区域,并且总运行时间为O(sqrt(n))。因此,边界O(n / k + sqrt(n))通常成立。我觉得这是最坏情况下的最佳情况,但我没有证据。

答案 2 :(得分:0)

它可以在O(log 2 n)中解决。

  1. 如果在中点处斜率下降,我们就在p..q范围内。
  2. 如果在中点处斜率增加,我们要么在1..p范围内,要么在q..n范围内。
    • 1.. mid pointmid point..n范围内执行二进制搜索,以寻找斜率下降的值。它只能在其中一个范围内找到。现在我们知道中点所在的1..pq..n子范围。
  3. 重复从(1)到包含峰值的子范围的过程,直到达到p..q范围。
  4. 通过在Divide and conquer algorithm applied in finding a peak in an array.
  5. 中应用算法来查找子范围中的峰值
  6. 在范围1..p,p..q,q..n。
  7. 中执行3次二进制搜索

    ==&GT;总体复杂性为O(log 2 n)。