对已旋转 N 次的排序数组进行二进制搜索的最佳方法是啥[重复]

Posted

技术标签:

【中文标题】对已旋转 N 次的排序数组进行二进制搜索的最佳方法是啥[重复]【英文标题】:What is the best way to do a binary search on a sorted array which has been rotated N times [duplicate]对已旋转 N 次的排序数组进行二进制搜索的最佳方法是什么[重复] 【发布时间】:2011-02-06 05:08:23 【问题描述】:

可能重复:Searching a number in a rotated sorted Array

我有一个排序数组,它已经被右旋转了 N 次,其中 N 是未知的。现在我想对其进行二进制搜索。怎么办?

eg initial array 1 4 5 8 15

now roted N=1 time   15  1  4  5  8
N= 2                  8 15  1  4  5 

N 可以是任意值,并且可以大于元素个数。

【问题讨论】:

你到底为什么要这么做? 可能是一个面试问题。一种幼稚且低效的方法是再次使用数组并执行二进制搜索哈哈 如果元素可以重复,在最坏的情况下你不能比 Omega(n) 做得更好。考虑一个全为零的数组,除了一个,它是一。 这不是完全重复的。那个相关的可能问题是关于搜索已知数字的;而这谈论的是找到未知的最小值的位置。 你可能会找到2个转换点,它将数组分成3个排序数组。然后对所有 3 个数组进行二进制搜索以找到您要查找的元素。要找到过渡点,只需进行二进制搜索,直到剩下 2 个元素,其中一个是 而不是 k。 k 可以是数组中的任意数字,例如中点。 O(log n) 需要找到转换点,并且 O(log n) 需要对所有 3 个子阵列进行 BS。 【参考方案1】:

简短的回答是,您没有(至少,不是一次在整个阵列上)。这是因为二分搜索需要对元素进行排序才能工作。

您可以做的最好的事情是使用二进制搜索分别搜索数组的每一半。例如,继续上面的示例,如果 N = 2,您的数组将变为 8 15 1 4 58 151 4 5 仍处于排序状态,因此您可以对每个子数组进行二分搜索。在一般意义上,算法因此变为:

Let your array be A, its length be M, and the target value be T.
If (N is 0 or a multiple of M)
    Binary search A for T
Else
    The sub-array A1 is the first (M mod N) elements of A.
    The sub-array A2 is the remaining (M - (M mod N)) elements of A.
    If (the first element of A <= T)
        Binary search A1 for T
    Else
        Binary search A2 for T

您可以根据 A 的第一个元素将搜索限制在 A1 或 A2 的原因是因为如果 A[0] > T,那么根据定义,A1 的所有元素也将 > T,因此 T 不能在 A1 中。

HTH!

编辑 正如 Chris 在下面的 cmets 中指出的那样,有一种比这更简单的方法实际上可以让您继续对整个数组执行二进制搜索。虽然上述方法可行,但他的方法巧妙地执行了类似的功能,但通过使用修改后的比较操作在整个数组上执行。

【讨论】:

你的第一段是错误的。关键的见解是,如果你有一个排序数组并旋转它,结果是一个具有不同比较函数的排序数组。具体来说,比较是x 小于y iff (x &lt; y) || (x &gt; A[0] &amp;&amp; y &lt; A[0])。然后,您可以使用此比较进行二分搜索。 @Chris:这是有道理的。我从来没有这样想过——它仍然是排序的,只是在不同的定义下。这真是大开眼界。 如果允许元素重复,Chris 的解决方案和这个解决方案都不起作用。 根据您上面自己的评论,二分搜索使用重复值,它只会导致次优性能。我在上面的回复中的关键见解(克里斯也依赖于此)是,在旋转之后,数组由两个子数组组成,这两个子数组仍然是排序的。因此,根据定义,算法仍然有效,尽管您描述的性能受到影响。他们当然不会停止工作。 @Mac:它们不起作用。在某些情况下,算法会声称数组不包含这样的元素,而它确实如此。我对这个问题的评论不适用于您或 Chris 的算法。它谈论正确算法。任何正确的算法都将具有 Omega(n) 最坏情况下限。事实上,这足以证明这些(你和 Chris 的)算法是不正确的,因为在最坏的情况下它们是 O(logn)。顺便说一句,如果您使用@Moron,我会收到您对我评论的回复的通知(这是本网站的一项功能)。

以上是关于对已旋转 N 次的排序数组进行二进制搜索的最佳方法是啥[重复]的主要内容,如果未能解决你的问题,请参考以下文章

给定一个旋转的排序数组,我怎样才能找到该数组中的最大值?

153. 寻找旋转排序数组中的最小值

问题列表

分治1:33. 搜索旋转排序数组

Leetcode No.153 寻找旋转排序数组中的最小值(二分查找)

Leetcode No.153 寻找旋转排序数组中的最小值(二分法)