我很难解决这个问题。
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)
答案 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)中解决。
p..q
范围内。1..p
范围内,要么在q..n
范围内。
1.. mid point
和mid point..n
范围内执行二进制搜索,以寻找斜率下降的值。它只能在其中一个范围内找到。现在我们知道中点所在的1..p
和q..n
子范围。 p..q
范围。==&GT;总体复杂性为O(log 2 n)。