简体   繁体   English

在int数组上使用二进制搜索按降序排序

[英]Use a Binary Search on an int array sorted in descending order

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;
    }
}

For an assignment in class I need to modify the BinarySearch method so that it will work properly with the reversed array. 对于类中的赋值,我需要修改BinarySearch方法,以便它可以与反向数组一起正常工作。 But I can't figure out how I'm supposed to modify it. 但我无法弄清楚我应该如何修改它。

If the array is sorted in descending order, binary search can still work if you reverse the sense of all value comparisons performed by the search algorithm. 如果数组按降序排序,则如果反转搜索算法执行的所有值比较的意义,二进制搜索仍然可以工作。

The equals case is still fine, but you can reverse the comparison made in the else if to a < . 等于大小写的情况仍然没有问题,但你可以将else if的比较反转为< The else doesn't need to be modified, because the else if change means the else block will now represent the > condition. else不需要修改,因为else if change意味着else块现在将代表>条件。

Binary search makes the assumption the data is ordered . 二进制搜索假设数据是有序的 If that's the case, than one knows if the value of the selected index ( mid ) is less than the value, the value must be in the range 0..mid-1 and vice versa. 如果是这种情况,则不知道所选索引( mid )的值是否小于该值,该值必须在0..mid-1范围内,反之亦然。

In case the array is ordered in reverse, one knows that if the value is less, then one must search in the second part. 如果数组反向排序,则可以知道如果值较小,则必须在第二部分中搜索。 The only thing you must modify is the condition in the else if : 您必须修改的唯一内容是else if的条件, else if

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

That said, one better makes the method a bit more generic so one can make the comparator more generic as well: 也就是说,一个更好的方法使该方法更通用,因此可以使比较器更通用:

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;
}

In case you provide a reversed array, you only need to provide a Comparator<T> that returns -val with val the comparator for the original array. 如果你提供反向数组,你只需要提供一个Comparator<T> ,它返回-val其中val是原始数组的比较器。

There is a hack: 1) Reverse whole array so that now it is increasing order array. 有一个hack:1)反向整个数组,现在它正在增加顺序数组。 2) Apply binary search and then find suitable index. 2)应用二进制搜索,然后找到合适的索引。 3) n-index will be your answer. 3)n-index将是你的答案。

Binary searches work on sorted sets. 二进制搜索适用于有序集。 Your code assumes that the order is ascending, yet, it is the inverse. 您的代码假定订单是递增的,但它是反向的。 As a result, you need to invert the condition: 因此,您需要反转条件:

while(lb > ub){

On more general terms, you could be agnostic about the direction: 更笼统地说,你可能对方向不了解:

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;
}

and use ascending order by default: 并默认使用升序:

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

but descending in your case 但在你的情况下下降

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);
}

Just change srchVal > a[mid] condition to srchVal < a[mid] 只需将srchVal> a [mid]条件更改为srchVal <a [mid]

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));
     }
}

You can pass a reverse comparator in the binary search when you want to run the binary search in an array which is sorted in descending order. 如果要在按降序排序的数组中运行二进制搜索,则可以在二进制搜索中传递反向比较器。 Example: 例:

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.

The above function will return 4 which is the index of 2 in reverse sorted array. 上面的函数将返回4,这是反向排序数组中的2的索引。 It also works as usual if the element is not present in the array. 如果元素不存在于数组中,它也可以正常工作。 For example, if you search of value 3, it will return -5. 例如,如果搜索值3,它将返回-5。 (-insertion index -1) Check this for details. (-insertion指数-1)检查了解详情。

Thanks 谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM