【问题标题】:Use a Binary Search on an int array sorted in descending order对按降序排序的 int 数组使用二分查找
【发布时间】:2019-09-03 21:03:33
【问题描述】:
import java.util.*;
import java.io.*;
import java.util.Arrays;
import java.util.Collections;
import org.apache.commons.lang3.ArrayUtils;
@SuppressWarnings("unused")
public class Tester {
    public static void main(String args[]){
        int i[] = {-7, 15, 21, 22, 43, 49, 51, 67, 81, 84, 89, 95, 97};
        ArrayUtils.reverse(i);
        System.out.println(binarySearch(i, 22));
        System.out.println(binarySearch(i, 89));
        System.out.println(binarySearch(i, -100));
        System.out.println(binarySearch(i, 72));
        System.out.println(binarySearch(i, 102));
    }
    private static int binarySearch(int a[], int srchVal){
        int lb = 0;
        int ub = a.length - 1;

        while(lb <= ub){
            int mid = (lb + ub)/2;
            if(a[mid] == srchVal){
                return mid;
            }
            else if(srchVal > a[mid]){
                lb = mid + 1;
            }
            else{
                ub = mid - 1;
            }
         }
        return -1;
    }
}

对于类中的分配,我需要修改 BinarySearch 方法,以便它可以与反转数组一起正常工作。但我不知道我应该如何修改它。

【问题讨论】:

  • 为了提高效率,我会在 binarySearch 方法中最后检查 '==' 的情况。平等是最不可能发生的情况,并且肯定只能发生一次(当您找到元素时)。因此,按照编码,您首先检查租赁可能的情况。

标签: java sorting binary-search


【解决方案1】:

如果数组是按降序排序的,如果你反转搜索算法执行的所有值比较的意义,二分搜索仍然可以工作。

equals 的情况仍然可以,但您可以将else if 中的比较反转为&lt;else 不需要修改,因为 else if 更改意味着 else 块现在将代表 &gt; 条件。

【讨论】:

    【解决方案2】:

    二分搜索假设数据是有序。如果是这种情况,就会知道所选索引的值 (mid) 是否小于该值,该值必须在 0..mid-1 范围内,反之亦然。

    如果数组是倒序排列的,则知道如果值较小,则必须在第二部分进行搜索。唯一需要修改的是else if中的条件:

    else if(srchVal < a[mid]){ //change < to >
        lb = mid + 1;
    }
    

    也就是说,更好的方法是让方法更通用一点,这样比较器也可以更通用:

    private static<T> int binarySearch(T[] a, Comparator<T> c, T srchVal){
        int lb = 0;
        int ub = a.length - 1;
    
        while(lb <= ub){
            int mid = (lb + ub)/2;
            int ci = c.compare(a[mid],srchVal);
            if(ci == 0){
                return mid;
            }
            else if(ci < 0){
                lb = mid + 1;
            }
            else{
                ub = mid - 1;
            }
         }
        return -1;
    }
    

    如果您提供一个反转数组,您只需要提供一个返回 -valComparator&lt;T&gt; 和原始数组的比较器 val

    【讨论】:

      【解决方案3】:

      当您想在按降序排序的数组中运行二进制搜索时,您可以在二进制搜索中传递反向比较器。 示例:

      Integer [] arr = new Integer[]{5,6,2,9,7};
      Arrays.sort(arr, Collections.reverseOrder()); //sorting the array in descending order
      Arrays.binarySearch(arr, 2, Comparator.reverseOrder()) // Searches of for 2 in the array.
      

      上述函数将返回 4,即 2 在反向排序数组中的索引。 如果元素不存在于数组中,它也照常工作。 例如,如果您搜索值 3,它将返回 -5。 (-插入索引-1) 详情请查看this

      谢谢

      【讨论】:

        【解决方案4】:

        有一个技巧: 1)反转整个数组,以便现在它是递增顺序数组。 2)应用二分搜索,然后找到合适的索引。 3) n-index 将是您的答案。

        【讨论】:

        • 仅反转条件比反转整个数组要好得多,请参阅我的答案。
        【解决方案5】:

        只需将 srchVal > a[mid] 条件更改为 srchVal

        import java.util.*;
        
        import java.io.*;
        
        import java.util.Arrays;
        
        import java.util.Collections;
        
        public class HelloWorld{
        
            private static int binarySearch(int a[], int srchVal){
                int lb = 0;
                int ub = a.length - 1;
        
                while(lb <= ub){
                    int mid = (lb + ub)/2;
                    if(a[mid] == srchVal){
                        return mid;
                    }
                    else if(srchVal < a[mid]){
                        lb = mid + 1;
                    }
                    else{
                        ub = mid - 1;
                    }
                 }
                return -1;
            }
        
             public static void main(String []args){
                 int i[] = {97,95,89,84,81,67,51,49,43,22,21,15,-7};
                 System.out.println(binarySearch(i, 22));
                 System.out.println(binarySearch(i, 89));
                 System.out.println(binarySearch(i, -100));
                 System.out.println(binarySearch(i, 72));
                 System.out.println(binarySearch(i, 102));
             }
        }
        

        【讨论】:

          【解决方案6】:

          二进制搜索适用于排序集。您的代码假定顺序是升序的,但它是相反的。因此,您需要反转条件:

          while(lb > ub){
          

          更笼统地说,您可能不知道方向:

          private static int binarySearch(int a[], int srchVal, boolean isAscending){
              int lb = 0;
              int ub = a.length - 1;
          
              while((lb <= ub) == isAscending){
                  int mid = (lb + ub)/2;
                  if(a[mid] == srchVal){
                      return mid;
                  }
                  else if(srchVal > a[mid]){
                      lb = mid + 1;
                  }
                  else{
                      ub = mid - 1;
                  }
               }
              return -1;
          }
          

          并默认使用升序:

          private static int binarySearch(int a[], int srchVal){
              return binarySearch(a, srchVal, true);
          }
          

          但在你的情况下会下降

          public static void main(String args[]){
              int i[] = {-7, 15, 21, 22, 43, 49, 51, 67, 81, 84, 89, 95, 97};
              ArrayUtils.reverse(i);
              System.out.println(binarySearch(i, 22), false);
              System.out.println(binarySearch(i, 89), false);
              System.out.println(binarySearch(i, -100), false);
              System.out.println(binarySearch(i, 72), false);
              System.out.println(binarySearch(i, 102), false);
          }
          

          【讨论】:

          • 我想知道投反对票的原因是为了改进这个答案。
          猜你喜欢
          • 2011-11-16
          • 1970-01-01
          • 1970-01-01
          • 2021-12-06
          • 1970-01-01
          • 1970-01-01
          • 2014-02-16
          • 2016-03-28
          相关资源
          最近更新 更多