如何确定哪个索引有一个已排序的数组?

时间:2012-08-07 23:47:30

标签: algorithm binary-search

给定一个数组,例如[7,8,9,0,1,2,3,4,5,6],是否可以确定旋转发生得比O(n)更快的索引?

使用O(n),只需遍历所有元素并将第一个递减元素标记为索引。

一个可能更好的解决方案是从两端向中间迭代,但这仍然是O(n)的最坏情况。

6 个答案:

答案 0 :(得分:3)

(编辑:下面假设元素是不同的。如果它们不相同,我认为没有比扫描数组更好的了。)

您可以二进制搜索它。我不会发布任何代码,但这里是一般性的想法:(对于其余部分,我会假设a >= b。如果a < b,那么我们知道它仍处于排序顺序中)

取第一个元素,称之为a,最后一个元素b和中间元素,称之为c

如果a < c,那么您知道枢轴位于cb之间,您可以递归(使用cb作为新的结束)。如果a > c,那么您知道枢轴介于两者之间,并在那一半递归(以ac作为结束)。

ADDENDUM:要扩展到包含重复的案例,如果我们有a = c > b,那么我们会以cb作为我们的结束,而如果a = c = b,则我们会从a进行扫描cd以查看是否存在某些元素a,使其不同。如果它不存在,则cc之间的所有数字都相等,因此我们以ba > d < b作为我们的结果递归。如果是,则有两种情况:

d:此处a < d > b是我们从左侧扫描后的最小元素,我们已经完成了。
d:在这里,我们知道答案介于bO(log n)之间,因此我们将这些作为我们的目标。

在最好的情况下,我们永远不必使用相等的情况,给我们O(n)。最糟糕的情况是,这些扫描几乎包含所有阵列,给我们{{1}}。

答案 1 :(得分:2)

对于N个数组的数组,如果数组旋转最少1次且少于N次,我认为它可以正常工作:

int low=0, high = n-1;
int mid = (low +high)/2;
while( mid != low && mid != high)
 {
  if(a[low] < a[mid])
  low = mid;
  else
  high = mid;
  mid = (low + high)/2;
 }
return high;

答案 2 :(得分:1)

您可以使用二进制搜索。如果您选择1作为中心值,则您知道中断是在前半部分,因为7&gt; 1&lt; 6。

答案 3 :(得分:0)

一个观察结果是,移位等于最小元素的索引。因此,您所要做的就是使用二进制搜索来查找最小元素。唯一的问题是,如果数组具有相同的元素,那么任务就会变得有点棘手:你无法获得比O(N)时间更好的大O效率,因为你可以在[0, 0, 0, 0, ..., 100, 0, 0, 0, ..., 0]之类的输入中获得当然,找到比线性更快的唯一非零元素。但是仍然以下算法达到O(Mins + Log(N)),其中Mins是最小元素的数量,如果array[0]是最小值之一(否则Mins = 0不给予惩罚)。

l = 0;
r = len(array) - 1;
while( l < r && array[l] == array[r] ) {
    l = l + 1;
}

while( l < r ) {
    m = (l + r) / 2;
    if( array[m] > array[r] ) {
        l = m + 1;
    } else {
        r = m;
    }
}

// Here l is the answer: shifting the array l elements left will make it sorted

这适用于O(log N)的唯一元素数组,O(N)适用于非唯一元素数组(但仍然比大多数输入的天真解决方案更快)。

答案 4 :(得分:0)

前提条件

  • 数组按升序排序
  • 阵列左转

方法

  • 首先,我们需要找到最小元素所在的索引。
  • 数组旋转的次数将等于数组长度与最小元素所在的索引的差值。

所以任务是找到最小元素的索引。我们可以通过两种方式找到最低元素的索引

方法1 -

  • 只是遍历数组,当当前元素小于下一个元素时,当前索引是最小元素的索引。在最坏的情况下,这将采用O(n)

方法2

  • 使用(lowIndex + highIndex)/ 2
  • 查找中间元素
  • 然后我们需要找到中间元素的哪一侧我们可以找到最小的元素,因为它可以在中间元素的左侧或右侧找到
  • 我们将第一个元素与中间元素进行比较,如果第一个元素大于中间元素,那么它意味着最小元素位于中间元素的左侧并且
  • 如果第一个元素小于中间元素,则可以在中间元素的右侧找到最低元素

所以这可以像二进制搜索一样应用,在O(log(n))中我们可以找到最小元素的索引

答案 5 :(得分:0)

使用递归方法:

static void Main(string [] args)         {             var arr = new int [] {7,8,9,0,1,2,3,4,5,6};             Console.WriteLine(FindRotation(ARR));         }

    private static int FindRotation(int[] arr)
    {
        var mid = arr.Length / 2;
        return CheckRotation(arr, 0, mid, arr.Length-1);
    }

    private static int CheckRotation(int[] arr, int start, int mid, int end)
    {
        var returnVal = 0;
        if (start < end && end - start > 1)
        {
            if (arr[start] > arr[mid])
            {
                returnVal = CheckRotation(arr, start, start + ((mid - start) / 2), mid);
            }
            else if (arr[end] < arr[mid])
            {
                returnVal = CheckRotation(arr, mid, mid + ((end - mid) / 2), end);
            }
        }
        else
        {
            returnVal = end;
        }

        return returnVal;
    }
相关问题