在O(log n)时间内找到[j] = j

时间:2010-10-28 01:07:52

标签: algorithm

如何在O(log n)时间内找到排序数组是否具有元素a [j] = j?(无重复)

5 个答案:

答案 0 :(得分:13)

如果数组是整数且不能包含重复项,则可以使用二进制搜索。

E.g。假设我们有阵列:

a[0] == -30
a[1] == 1
a[2] == 200
a[3] == 200
a[4] == 204
a[5] == 205
a[6] == 206
a[7] == 207
  • 首先尝试[楼层(平均(0,7))](即 [3])。这相当于200. 200也是 大。
  • 所以搬到下半部分。尝试 a [floor(avg(0,2))](即a [1])。这个 等于1.华友世纪!

你的二进制搜索会成功找到一些j为[j] == j的j,或者它会因为用尽的地方而失败。由于二进制搜索是O(log n),你将在该时间复杂度内知道j的值或不存在这样的j。

请注意,如果j的多个值满足条件,您将只找到它们中的任意一个。

答案 1 :(得分:8)

如果它可以包含重复值,或者它是浮点数组,则不能。反例:a [2k] = 2k + 1,a [2k + 1] = 2k + 1或2k + 2。最糟糕的情况是,您必须为所有k检查[2k + 1]。

如果它是一个整数数组且所有值都是不同的,那么你进行二分查找。看一下[1] -1和[n] -n。如果它们是相同的标志,答案是否定的。如果它们有不同的符号,请查看[n / 2] -n / 2。它是零(然后你有你的答案),或者其中一个间隔(1,n / 2)或(n / 2,n)在末端会有不同的符号。取这个间隔重复一遍。

答案 2 :(得分:1)

假设不允许重复:

#include <stdio.h>

int
find_elt_idx_match( int *a, int lo, int hi )
{
  int elt, idx;
  while ( lo <= hi )
    {
      idx = lo + ( hi - lo ) / 2; /* Thanks, @andand */
      elt = a[ idx ];
      if ( elt == idx )
        {
          return 1;
        }
      if ( elt < idx )
        {
          lo = idx + 1;
        }
      else
        {
          hi = idx - 1;
        }
    }
  return 0;
}

int
main( void )
{
  int a[ 100 ];
  /* fill a */
  /* ... */
  printf( "idx:elt match? %c\n", find_elt_idx_match( a, 0, 99 ) ? 'y' : 'n' );
  return 0;
}

答案 3 :(得分:0)

public int getFirstMatchedIndex(int[] oArry)
        {            
            int i = 0;
            while(i < oArry.Length )
            {
                if (oArry[i] == i)
                    return i;
                else if (oArry [i] > i)
                    i=oArry [i];
                else
                    i++;

            }
            return -1;
        }

答案 4 :(得分:0)

如果不允许重复,并且您的列表按照明显的顺序排序a [i]&lt; a [i + 1](严格地说,不等于!),那么a [i] -i&lt; a [i + 1] - i,因此a [i] -i&lt; = a [i] - (i + 1)。 (注意不等式变为“&lt; =”。)换句话说,整个列表中a [i] -i的值是有序的。搜索值0 = a [i] -i,在排序列表上使用二进制搜索。