检查数组中是否存在首先增加然后减少然后增加的数字

时间:2014-02-07 11:53:28

标签: arrays algorithm search

给定一个数组首先增加然后在某一点减少并再次增加? 找到给定数字N是否存在于数组中。

示例1:

Array = 7,8,3,4,5,6 
number = 7 
答案应该是真的。

示例2:

Array = 3,4,6,7,8,5,9,10,11  
number = 10

答案应该是真的。 所有数字都是唯一的。

可以在O(N)中使用线性搜索完成, 我们能做到这一点吗? (更有效率)

4 个答案:

答案 0 :(得分:1)

一般来说,没有。假设我们在Python中有以下内容:

l = range(n)

我们在那里随机贴上-1

if random.random() < 0.5:
    l[random.randrange(len(l))] = -1

判断列表中是否有-1的唯一方法是查看每个元素,直到找到它为止。列表的结构最终没有任何帮助。

答案 1 :(得分:0)

线性搜索与非线性数组一样好

答案 2 :(得分:0)

优化算法: -

  
      
  1. 如果找到则使用二进制搜索数组上的键,然后返回true。
  2.   
  3. 如果未找到,请使用线性搜索
  4.   

时间复杂度: -

搜索失败:在这里我们会进行线性搜索和二进制搜索,因此对于大输入来说是O(N)

成功搜索:这是我们的优化在某种程度上的工作。您最终在二进制搜索中搜索数组右侧部分的概率为1/2。因此平均搜索速度至少快2倍。

优化算法的Java代码及其结果: -

public class UniqueSearch {
    static int linearCount = 0;
    public static boolean binSearch(int[] arr,int key,int high,int low) {


        while(high>=low) {
            int mid = (low+high)/2;
            if(arr[mid]==key) 
                return(true);
            if(arr[mid]<key) {
                low = mid+1;
            }
            else {
                high = mid-1;
            }
        }
        return(false);
    }

    public static boolean linearSearch(int arr[],int key) {
        //System.out.println("linearSearch");
        linearCount++;
        for(int i=0;i<arr.length;i++) {
            if(key==arr[i]) {
                return(true);
            }
        }
        return(false);
    }


    public static boolean optSearch2(int arr[],int key) {

        boolean flag = binSearch(arr, key, arr.length-1,0);
        if(!flag) {
            return(linearSearch(arr, key));
        }
        return(flag);
    }

    public static void main(String[] args) {

        int n = 100000;
        int[] arr = new int[n];
        int error = 0;
        Random r = new Random();
        long start = System.currentTimeMillis();
        int totalCount = 0;
        for(int i=0;i<1000;i++) {
            error = r.nextInt(arr.length-1);
            for(int k=0;k<error;k++) {
                arr[k] = 2*k+1;
            }
            for(int k=error;k<arr.length;k++) {
                arr[k] = 2*(k-error);
            }
            for(int j=0;j<1000;j++) {
                int x = r.nextInt(arr.length); 
                totalCount++;
                    boolean flag = optSearch2(arr,arr[x]);
                    if(!flag) {
                        System.out.println("error");
                    }

            }
        }
        System.out.println("linearSearch Percentage: "+linearCount*100/totalCount);
        System.out.println(System.currentTimeMillis()-start);
    } 
}

结果:

运行代码并等待6-7秒,您将看到随机成功搜索特殊类型的随机数组,因为您的问题需要大约30%的线性搜索,并且可以使用{{{}中的二进制搜索来完成休息1}}

答案 3 :(得分:0)

可以在O(logN)时间复杂度

中完成
  1. 在数组中查找最大元素(调用此数据透视图)。这是伪代码

    public static int getMax(int start, int end){
    
    if(start==end)
        return start;
    if(start>end)
        return -1;
    
    int mid = start + (end-start)/2;
    // check if maxima
    if(arr[mid-1]<arr[mid] && arr[mid]>arr[mid+1])
        return mid;
    
    // check slope
    if(arr[mid-1]<arr[mid] && arr[mid]<arr[mid+1]){
        //increasing slope
        return getMax(mid+1, end);
    }
    if(arr[mid-1]>arr[mid] && arr[mid]>arr[mid+1]){
        return getMax(start, mid-1);
    }
    
    return -1;
    }
    
  2. 在pivot元素上的分区数组并运行左(增加)和右(减少)的两个二项式搜索

    findElem(int key, int pivot){
      int index = binSearchInc(start, pivot-1);
      if(index>=0)
        return index;
      else 
        return binSearchDec(pivot+1, end);
    }
    
  3. 这两个步骤都需要O(logN)时间来执行。