【问题标题】:find an element in infinite sorted array在无限排序数组中找到一个元素
【发布时间】:2012-09-21 17:24:27
【问题描述】:

这是面试题...

已排序的无限数组,并且从某个位置(我们不知道该位置)只有特殊符号“$”才会出现,我们需要在该数组中找到一个元素...

我给出了一个解决方案,例如获取 $ 的第一次出现,然后从 $ 对前一部分进行二进制搜索

要找到 $ i 的第一次出现,如果 (i,2i) 给出了增加窗口大小的解决方案

我给出的代码是

#include<stdio.h>

int first(int *arr,int start,int end,int index)
{
    int mid=(start+end)/2;
    if((mid==start||arr[mid-1] != '$') && arr[mid]=='$')
        return mid;
    if(arr[mid]=='$')
        return first(arr,start,mid-1,index);
    else
    {
        if(arr[end] =='$')
            return first(arr,mid+1,end,index);
        else
            return first(arr,end+1,(1<<index),index+1);
    }
}

int binsearch(int *arr,int end ,int n)
{
    int low,high,mid;
    high=end-1;
    low=0;
    while(low<= high)
    {
        mid=(low+high)/2;
        if(n<arr[mid])
            high=mid-1;
        else if (n >arr[mid])
            low=mid+1;
        else
            return mid;
    }
    return -1;
}

int main()
{
    int arr[20]={1,2,3,4,5,6,7,8,9,10,'$','$','$','$','$','$','$','$','$','$'};
    int i =first(arr,0,2,2);
    printf("first occurance of $ is  %d\n",i);
    int n=20;//n is required element to be found
    if(i==0||arr[i-1]<n)
        printf(" element %d not  found",n);
    else{
        int p=binsearch(arr,i,n);
        if(p  != -1)
            printf("element %d is found at index %d",n,p);
        else
            printf(" element %d not found",n);
    }
    return 0;
}

有没有更好的方法来解决上述问题??

我也想知道找到 $ 的第一次出现为什么我们应该只以 2 的幂移动窗口为什么不像 (i,3i) 这样的 3 来移动窗口

有人可以对重复关系有所了解吗..请帮助..

【问题讨论】:

  • 问题的第二部分(在找到 $ 符号之后)与 this thread 相关 [注意 - 这不是骗局,但不是投票关闭或任何事情]

标签: arrays algorithm


【解决方案1】:

对我来说似乎是个不错的方法。作为一个小的优化,当您到达比您正在搜索的数字更大的任何数字(不仅仅是$)时,您可以停止您的first 例程。

将窗口扩大 2 的幂意味着您将在 log_2(n) 迭代中找到结尾。以 3 倍增长意味着您将在 log_3(n) 迭代中找到它,它更小。但不是越来越小,如O(log_2(n)) == O(log_3(n))。而且您的二分搜索无论如何都会采用log_2(n) 步骤,因此使first 部分更快不会帮助您的big-O 运行时间。

【讨论】:

    【解决方案2】:

    迭代格式的第一个函数的有效部分是

    private int searchNum(int[] arr, int num, int start, int end) {
        int index = 0;
        boolean found = false;
        for (int i = 0; i < arr.length; i = 1 << index) {
            if (start + i < arr.length) {
                if (arr[start] <= num && arr[start + i] >= num) {
                    found = true;
                    return bsearch(arr, num, start, start + i);
                } else {
                    start = start + i;
                }
            } else {
                return bsearch(arr, num, start, arr.length - 1);
            }
        }
        return 0;
    }
    

    这不会让您第一次出现,而是尝试直接查找数字,因为在您的情况下,您甚至在找到 $ 符号之前就错过了可以找到数字本身的概率。所以最坏情况的复杂度是 O(logn).. 最好的情况是(1) 之后你把它传递给

    private int bsearch(int[] array, int search, int first, int last) {
        int middle = (first + last) / 2;
        while (first <= last) {
            if (array[middle] < search)
                first = middle + 1;
            else if (array[middle] == search) {
                System.out.println(search + " found at location "
                        + (middle + 1) + ".");
                return middle;
            } else
                last = middle - 1;
    
            middle = (first + last) / 2;
        }
        if (first > last)
            System.out.println(search + " is not present in the list.\n");
        return -1;
    }
    

    调用函数

        if ((pos = searchNum(arr, num, 0, 2)) != -1) {
            System.out.println("found @ " + pos);
        } else {
            System.out.println("not found");
        }
    

    【讨论】:

      【解决方案3】:

      这是python解决方案。

      arr = [3,5,7,9,10,90,100,130,140,160,170,171,172,173,174,175,176]
      elm = 171
      k = 0
      while (True):
          try:
              i = (1 << k) - 1 #  same as 2**k - 1 # eg 0,1,3,7,15
              # print k
              if(arr[i] == elm):
                  print "found at " + str(i)
                  exit()
              elif( arr[i] > elm):
                  break                   
      
          except Exception as e:          
              break
          k = k+1
      
      begin = 2**(k-1) # go back to previous power of 2
      end = 2**k -1 
      
      # Binary search
      while (begin <= end):
          mid = begin + (end-begin)/2
          try:
              if(arr[mid] == elm):
                  print "found at " + str(mid)
                  exit()          
              elif(arr[mid] > elm):
                  end = mid-1
              else:
                  begin = mid+1
      
          except Exception as e:
              # Exception can occur if you are trying to access min element and that is not available. hence set end to mid-1
              end = mid-1
      
      
      print "Element not found"
      

      【讨论】:

        猜你喜欢
        • 2012-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-29
        • 1970-01-01
        • 1970-01-01
        • 2021-02-04
        相关资源
        最近更新 更多