创建了我自己的二进制搜索版本,不明白为啥它比常规方法更快?

Posted

技术标签:

【中文标题】创建了我自己的二进制搜索版本,不明白为啥它比常规方法更快?【英文标题】:Created my own version of Binary Search, can't understand why it is faster than the regular approach?创建了我自己的二进制搜索版本,不明白为什么它比常规方法更快? 【发布时间】:2020-01-02 22:44:22 【问题描述】:

大家好,阅读这篇文章的人。我最近毕业了,基本上我会复习我学到的每一个概念,以刷新我的记忆或更好地提高我的技能,以便我可以申请公司并被录用。我的第一次复习是查看二分搜索,我决定编写自己的版本而不查看常规方法。我碰巧编写了以下代码,其中我将常规方法的时间复杂度与我自己的二进制搜索版本进行了比较。 虽然,我的二进制搜索似乎集成了线性搜索和二进制搜索,但它似乎比常规方法更快,我只是不明白为什么。当键大于中间元素时使用线性搜索,这似乎实际上会增加搜索的时间复杂度。您可以在我的 "myBinarySearch" 方法中最后一个 else if 条件的代码中看到这一点。 然而,即使在搜索了 15,000 个数组的整数之后,我的版本仍然更快。

谁能解释一下为什么我的版本更快?以下是与我的二进制搜索版本相比的常规方法。我的版本只是在搜索一个不存在且过度过度的键时比较慢,例如搜索 16,000。它一定是过度的,因为搜索 15,001 确实会导致返回 -1 的时间更快。

我得出的结论是,这是因为我只使用了一个变量,而不是在常规方法中使用 3 个变量,即在循环遍历数组时检查和/或更新这些变量。虽然,我的方法中最后一个 else if 语句中的线性搜索让我失望,让我想知道这如何不会增加时间复杂度。

public static void main(String[] args) 
    int[] array = new int[15000];
    File file; 
    BufferedReader br;
    try 
       file = new File("../Java/bin/IntroToJavaBook/largeArray.txt");
       br = new BufferedReader(new FileReader(file));
       String st;
       int i = 0;
       while((st = br.readLine()) != null) 
       
           array[i] = Integer.parseInt(st);
           i++;
       
     catch (FileNotFoundException e) 
       e.printStackTrace();
     catch (IOException e) 
       e.printStackTrace();
     

    int key = 4200;
    long startTime = System.nanoTime();
    System.out.println(binarySearch(array, key));
    long endTime = System.nanoTime();
    long duration = (endTime - startTime);
    System.out.println(duration);

    long startTime1 = System.nanoTime();
    System.out.println(myBinarySearch(array, key));
    long endTime1 = System.nanoTime();
    long duration1 = (endTime1 - startTime1);
    System.out.println(duration1);



static int binarySearch(int[] array, int key) 
    int low = 0;
    int high = array.length - 1;
    while (high >= low) 
    
        int mid = (low + high) / 2; 
        if (key < array[mid])
        
            high = mid - 1;
        
        else if (key == array[mid])
        
            return mid; 
        
        else
        
            low = mid + 1;
        
    
    return -1;


static int myBinarySearch(int[] array, int key) 
    int half = array.length/2;
    while(true)
    
        if(half == 0 || half == array.length)
        
            return -1;
        
        else if(key < array[half])
        
            half /= 2;
        
        else if(key == array[half])
        
            return half;
        
        else if(key > array[half])
        
            half = half + 1;
        
    

【问题讨论】:

如果没有看到 binarySearch 和 myBinarySearch 的代码就不能说太多 Mirco 基准测试很难正确执行,尤其是使用 JVM。你说你比较了时间复杂度,然后开始谈论每个更快的条件。回去再回顾一下时间复杂度的话题,基准测试与它无关。你应该在n 上得到一个简单的数学方程O()。传统的 bin 搜索是 O(log2(n)) 听起来像你的可能是 O(log2(n) + n/2) ,你可以从简单的代数中看到它更慢。基准测试通常衡量最佳/最差/小 n 种情况,并不会告诉您关于整个算法的太多信息。 当然不能再快了。编写代码的常用方法是half += half/2half -= half/2,具体取决于比较。 【参考方案1】:

您将复杂性与速度混为一谈。 在复杂度上,n>1000,即使您运行 n=500 的测试也是如此。

【讨论】:

以上是关于创建了我自己的二进制搜索版本,不明白为啥它比常规方法更快?的主要内容,如果未能解决你的问题,请参考以下文章

字符串或二进制数据将被截断。该语句已终止。不明白为啥? [复制]

不明白为啥 AsyncTask 给了我一个不兼容的类型

为啥 expo 弹出无法弹出 expo 应用程序?

功能运行太慢...我不明白为啥

问一个问题,为啥pacman搜索不到其他版本的内核

为啥在这个程序中使用指针而不是常规变量?