【问题标题】:Binary search if array contains duplicates如果数组包含重复项,则二进制搜索
【发布时间】:2012-03-30 22:45:45
【问题描述】:

嗨,

如果我们使用二分法在下面的数组中搜索 24,搜索键的索引是多少。

array = [10,20,21,24,24,24,24,24,30,40,45]

我对二进制搜索有疑问,如果数组有重复值,它是如何工作的。谁能澄清...

【问题讨论】:

  • 你是在问,'如果我要实现一个二分搜索并被赋予这个数组并被要求找到 24 的索引,我应该返回什么?或者你是在问'如果我通过其他人的二进制搜索实现运行这个数组,我懒得做,返回值是什么?'
  • 如果可能的话,你可以告诉这两种情况......那将不胜感激......
  • 显然结果将是数组[5]。

标签: duplicates binary-search


【解决方案1】:

它适用于唯一和非唯一数组。

def binary_search(n,s):
  search = s
  if len(n) < 1:
    return "{} is not in array".format(search)
  if len(n) == 1 and n[0] != s:
    return "{} is not in array".format(search)
  
  mid = len(n)//2
  ele = n[mid]
  if search == ele:
    return "{} is in array".format(search)
  elif search > ele:
    return binary_search(n[mid:],search)
  else:
    return binary_search(n[:mid],search)

【讨论】:

    【解决方案2】:

    为了完整起见,这里有一个打字稿中的示例,非递归版本(二进制运算符用于强制对整数进行操作,而不是浮点算术)示例很容易转换为其他类 C 语言:

    function binarySearch(array: number[], query: number): [number, number] {
        let from: number;
        let till: number;
    
        let mid = 0 | 0;
        let min = 0 | 0;
        let max = array.length - 1 | 0;
    
        while (min < max) {
            mid = (min + max) >>> 1;
    
            if (array[mid] < query) {
                min = mid + 1 | 0;
            } else {
                max = mid - 1 | 0;
            }
        }
    
        mid = min;
        min--;
        max++;
    
        from = array[mid] < query ? (array[max] === query ? max : mid) : (array[mid] === query ? mid : min);
    
        min = 0 | 0;
        max = array.length - 1 | 0;
    
        while (min < max) {
            mid = (min + max) >>> 1;
    
            if (query < array[mid]) {
                max = mid - 1 | 0;
            } else {
                min = mid + 1 | 0;
            }
        }
    
        mid = min;
        min--;
        max++;
    
        till = array[mid] > query ? (array[min] === query ? min : mid) : (array[mid] === query ? mid : max);
    
        return [from, till];
    }
    

    它的使用方法如下:

    let array = [1, 3, 3, 3, 5, 5, 5, 5, 5, 5, 7];
    
    console.log(binarySearch(array, 0)); // Gives [ -1,  0 ] <= No value found, note that resulting range covers area beyond array boundaries
    console.log(binarySearch(array, 1)); // Gives [  0,  0 ] <= Singular range (only one value found)
    console.log(binarySearch(array, 2)); // Gives [  0,  1 ] <= Queried value not found, however the range covers argument value
    console.log(binarySearch(array, 3)); // Gives [  1,  3 ] <= Multiple values found
    console.log(binarySearch(array, 4)); // Gives [  3,  4 ] <= Queried value not found, however the range covers argument value
    console.log(binarySearch(array, 5)); // Gives [  4,  9 ] <= Multiple values found
    console.log(binarySearch(array, 6)); // Gives [  9, 10 ] <= Queried value not found, however the range covers argument value
    console.log(binarySearch(array, 7)); // Gives [ 10, 10 ] <= Singular range (only one value found)
    console.log(binarySearch(array, 8)); // Gives [ 10, 11 ] <= No value found, note that resulting range covers area beyond array boundaries
    

    【讨论】:

      【解决方案3】:

      您提出的数组在中间索引中具有目标值,并且在最有效的实现中将在第一级递归之前返回该值。此实现将返回“5”(中间索引)。

      要了解算法,只需在调试器中逐步执行代码即可。

      public class BinarySearch {
          public static int binarySearch(int[] array, int value, int left, int right) {
                if (left > right)
                      return -1;
                int middle = left + (right-left) / 2;
                if (array[middle] == value)
                      return middle;
                else if (array[middle] > value)
                      return binarySearch(array, value, left, middle - 1);
                else
                      return binarySearch(array, value, middle + 1, right);           
          }
      
          public static void main(String[] args) {
              int[] data = new int[] {10,20,21,24,24,24,24,24,30,40,45};
      
              System.out.println(binarySearch(data, 24, 0, data.length - 1));
          }
      }
      

      【讨论】:

        【解决方案4】:

        正如@Pleepleus 所指出的,它将从第一级递归本身返回索引 5。不过我想指出一些关于二分搜索的事情:

        1. 不要使用mid = (left + right)/2,而是使用mid = left + (right-left)/2
        2. 如果要搜索元素的lower_boundupper_bound,请使用以下算法:

          binLowerBound(a, lo, hi, x)
            if (lo > hi)
              return lo;
          
            mid = lo +  (hi - lo) / 2;
            if (a[mid] == x)
              return binLowerBound(a, lo, mid-1, x);
            else if (a[mid] > x)
              return binLowerBound(a, lo, mid-1, x);
            else
              return binLowerBound(a, mid+1, hi, x);
          
          binHigherBound(a, lo, hi, x)
            if (lo > hi)
              return lo;
            mid = lo + (hi - lo) / 2;
            if (a[mid] == x)
              return binHigherBound(a, mid+1, hi, x);
            else if (a[mid] > x)
              return binHigherBound(a, lo, mid-1, x);
            else
              return binHigherBound(a, mid+1, hi, x);
          

        【讨论】:

        • 太棒了!不过只测试了下限!
        【解决方案5】:
        public class a{
            public static int binarySearch(int[] array, int value, int left, int right) {
                  if (left > right)
                        return -1;
                  int middle = (left + right) / 2;
                  if (array[middle] == value)
                {
                    if(array[middle-1]<array[middle])
                        return middle;
                         //return binarySearch(array, value, left, middle - 1);
                         else
                        return binarySearch(array, value, left, middle - 1);
                }
                  else if (array[middle] > value)
                        return binarySearch(array, value, left, middle - 1);
                  else
                        return binarySearch(array, value, middle + 1, right);           
            }
        public static int binarySearch1(int[] array, int value, int left, int right) {
                  if (left > right)
                        return -1;
                  int middle = (left + right) / 2;
                  if (array[middle] == value)
                {
                    if(array[middle]<array[middle+1])
                        return middle; 
                         else
        
                            return binarySearch1(array, value, middle + 1, right);           
                }
                  else if (array[middle] > value)
                        return binarySearch1(array, value, left, middle - 1);
                  else
                        return binarySearch1(array, value, middle + 1, right);           
            }
        
            public static void main(String[] args) {
                int[] data = new int[] {10,20,21,24,24,24,24,24,30,40,45};
        
        
                System.out.println(binarySearch(data, 24, 0, data.length - 1));     //First Index
                System.out.println(binarySearch1(data, 24, 0, data.length - 1));    //Last Index
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-16
          • 1970-01-01
          • 1970-01-01
          • 2020-02-28
          • 2016-01-19
          • 2012-01-04
          • 1970-01-01
          • 2020-11-16
          相关资源
          最近更新 更多