Java 面试问题-在排序数组X中搜索索引i,使X[i]=i

Java 面试问题-在排序数组X中搜索索引i,使X[i]=i,java,c++,arrays,algorithm,Java,C++,Arrays,Algorithm,在昨天的采访中,我被问到了以下问题: 考虑java或C++数组,如“代码> x ,排序后,两个元素中没有两个元素相同。如何才能最好地找到一个索引,比如说i,使该索引处的元素也是i。这就是X[i]=i 作为澄清,她还给了我一个例子: Array X : -3 -1 0 3 5 7 index : 0 1 2 3 4 5 Answer is 3 as X[3] = 3. 我能想到的最好的方法就是线性搜索。面试后,我对这个问题想了很多,但没有找到更好的解决办法。我的论点是:具有requir

在昨天的采访中,我被问到了以下问题:

考虑java或C++数组,如“代码> x <代码>,排序后,两个元素中没有两个元素相同。如何才能最好地找到一个索引,比如说

i
,使该索引处的元素也是
i
。这就是
X[i]=i

作为澄清,她还给了我一个例子:

Array X : -3 -1 0 3 5 7
index   :  0  1 2 3 4 5

Answer is 3 as X[3] = 3.
我能想到的最好的方法就是线性搜索。面试后,我对这个问题想了很多,但没有找到更好的解决办法。我的论点是:具有required属性的元素可以位于数组中的任何位置。所以它也可能在数组的最末端,所以我们需要检查每个元素


我只是想从这里的社区确认我是对的。请告诉我我是对的:)

有一些更快的解决方案,取O(对数n)的平均值,或者在某些情况下取O(对数n)而不是O(n)。在谷歌上搜索“二进制搜索”和“插值搜索”,你可能会找到很好的解释

如果数组是未排序的,那么是的,元素在任何地方,并且不能在O(n)之下,但排序数组不是这样

--

根据要求对插值搜索进行一些解释:

虽然二进制搜索仅涉及按“较大/不较大”比较两个元素,但插值搜索也尝试使用数值。关键是:你有一个从0到20000的排序范围。你看300-二进制搜索将从范围的一半开始,在10000。插值搜索猜测300可能比20000更接近于0,因此它将首先检查元素6000,而不是10000。然后,如果它太高,则递归到较低的子范围,如果它太低,则递归到较高的子范围

对于具有+-均匀分布值的大数组,插值搜索应该比二进制搜索快得多-编写代码并亲自查看。此外,如果首先使用一个插值搜索步骤,然后使用一个二进制搜索步骤,依此类推,效果最好


请注意,这是人类在字典中查找内容时凭直觉所做的事情。

您可以执行二进制搜索: 在中间搜索,如果值低于索引,则没有更低的索引将包含相同的值


然后搜索上半部分,继续搜索,直到找到元素,或到达一个元素范围。

这可以在
O(logN)
时间和
O(1)
空间中使用稍微修改的

考虑一个新数组
Y
,使得
Y[i]=X[i]-i

Array X : -3 -1   0  3  5  7
index   :  0  1   2  3  4  5
Array Y : -3 -2  -2  0  1  2
由于
X
中的元素的顺序是递增的,因此 新数组
Y
将按非降序排列。所以一个二进制 在
Y
中搜索
0
将给出答案

但是创建
Y
需要
O(N)
空间和
O(N)
时间。所以不是 创建新数组时,只需修改二进制搜索,使 对
Y[i]
的引用替换为
X[i]-i

算法:

function (array X) 
       low  = 0
       high = (num of elements in X) - 1

       while(low <= high) 
               mid = (low + high) / 2

               // change X[mid] to X[mid] - mid
               if(X[mid] - mid == 0)
                       return mid

               // change here too
               else if(X[mid] - mid < 0)
                       low = mid + 1;

               else
                       high = mid - 1;
       end while

       return -1 // no such index exists...return an invalid index.

end function
函数(数组X)
低=0
高=(X中的元素数)-1

虽然(低的顶部,我的头,做二进制分裂可能会更快

看看中间值,如果它很高,那么你需要什么,在下半部分重新搜索


经过一次比较后,您已经将数据集一分为二了

我认为这会更快

从列表中间开始< /P> 如果X[i]>i,则转到剩余左侧的中间

如果X[i]
继续这样做,每个循环的可能元素数量将减少一半。阅读问题后,似乎有一种情况可用于加速查找。在将位置与值进行比较时,如果值大于位置,则该值可以用作下一个要评估的位置。这将有助于更快地跳转数组。这是可以做到的,因为数组已排序。从概念上讲,我们跳过的值在数组中向左移动,并且位于错误的位置

例如:

int ABC[] = { -2, -5, 4, 7, 11, 22, 55 };
如果我的当前位置为2,且其值为4,则它们不相等,从概念上讲,值4向左移动。我可以使用值4作为我的下一个位置,因为如果值4不正确,则小于4的所有内容也不正确

以下示例代码仅供讨论:

void main()
{
    int X[] = { -3, -1, 0, 3, 5, 7};
    int length = sizeof(X)/sizeof(X[0]);

    for (int i = 0; i < length;) {
        if (X[i] > i && X[i] < length)
            i = X[i];                 // Jump forward!
        else if (X[i] == i) {
            printf("found it %i", i);
            break;
        } else
            ++i;
    }
}
void main()
{
int X[]={-3,-1,0,3,5,7};
int length=sizeof(X)/sizeof(X[0]);
对于(int i=0;ii&&X[i]
我想修改后的二进制搜索版本就足够了

假设序列是

Array : -1 1 4 5 6
Index :  0 1 2 3 4

Result : 1

从这两个示例中,我们可以看到,如果mid
mid <- (first + last )/2

if a[mid] == mid then
       return mid

else if a[mid] < mid then
        recursive call (a,mid+1,last)

else 
         recursive call (a,first,mid-1)
midJava:

公共静态布尔检查(int[]数组,int i)
{
if(i<0 | | i>=array.length)
返回false;
返回(数组[i]==i);
}
C++:

bool检查(int数组[],int数组大小,int i)
{
if(i<0 | | i>=数组大小)
返回false;
返回(数组[i]==i);
}

它不需要像@codaddict建议的那样考虑任何数组
Y

使用二进制搜索并检查给定数组的中间元素,如果它低于其索引,则不需要检查任何较低的索引,因为数组是 如果我们向左移动,减去m个索引和(至少)m个
mid <- (first + last )/2

if a[mid] == mid then
       return mid

else if a[mid] < mid then
        recursive call (a,mid+1,last)

else 
         recursive call (a,first,mid-1)
public static boolean check (int [] array, int i)
{
    if (i < 0 || i >= array.length)
        return false;

    return (array[i] == i);
}
bool check (int array[], int array_size, int i)
{
    if (i < 0 || i >= array_size)
        return false;

    return (array[i] == i);
}
int function(int[] arr) {
        int low = 0;
        int high = arr.length - 1;

        while(low <= high) {
            int mid = high - (high - low) / 2;

            if(arr[mid] == mid) {
                 return mid;
            } else if(arr[mid] < mid) {
                 low = mid + 1;
            } else {
                 high = mid - 1;
            }
        }

        return -1; // There is no such index
}
//invariant: startIndex <= i <= endIndex

int modifiedBsearch(int startIndex, int endIndex)
{
   int sameValueIndex = -1;
   int middleIndex = (startIndex + endIndex) /2;
   int middleValue = array[middleIndex];
   int endValue = array[endIndex];
   int startValue = array[startIndex];

   if(middleIndex == middleValue)
      return middleValue;
   else {
      if(middleValue <= endIndex)
         sameValueIndex = modifiedBsearch(middleIndex + 1, endIndex)

      if(sameValueIndex == -1 && startValue <= middleIndex)
         sameValueIndex = modifiedBsearch(startIndex, middleIndex -1);
   }

   return sameValueIndex;

}