Search code examples
javaarraylistbinary-search-tree

BinarySearch method in java


import java.util.*;

public class Practice {

static ArrayList<Integer> populateList(Scanner sc , ArrayList<Integer> al){
    String l = sc.nextLine();
    String arr[] = l.trim().split("\\s++");
    for(int i = 0; i<arr.length; i++){ 
        al.add(Integer.parseInt(arr[i]));
    }
    return al;
}
static void displayList(String s , ArrayList<Integer> al){
    System.out.print(s+": ");
    for(int i = 0; i<al.size(); i++){
        System.out.print(al.get(i)+" " );
    }
    System.out.println("");
}
static  ArrayList<Integer> sortListDesc(ArrayList<Integer> al ){
     Collections.sort(al,Collections.reverseOrder());
    return al;
}

static int binSearch(ArrayList<Integer> al , int key){
    
    int index = Collections.binarySearch(al,key,Collections.reverseOrder());
    return index+1;
}


public static void main(String[] args) {
    int key, index;
    Scanner sc = new Scanner(System.in); // Handle inputs
     
     // Create a list of Integers
     ArrayList<Integer> al = new ArrayList<Integer>();
    
     // Enter few numbers in a line and populate the list
     populateList( sc, al ); 
     
     // Display list
     displayList( "Original List", al );
     
     // Sort list in descending order
     sortListDesc( al );
     
     // Display sorted list
     displayList( "Sorted List", al );
     
     // Input key
     key = sc.nextInt();
     
     // Perform binary search for key in al
     index = binSearch(al, key);
     if (index >= 0)
    System.out.println("Position: " + index);
     else
    System.out.println("Not found");
       }
    }

/* Hers's My code , here in binSearch method i used the binarySearch method. i know that the binarySearch accepts only if the arrayList is in sorted in ascending order so i revesed it again in order to pass ascending order aList, but my question is if it sees the sorted in ascending order then how it gives the position of the descending order arraylist. for example if i give input 34 78 90 67 then it will sort in descending order 90 78 67 30 . but i have to revese as it again as it does not accept descending order array. so it gets acscending order array list 30 67 78 90 then when i pass the key(suppose 78) it should return the 3rd position ..but no it returns as descending order position 2 why this happens? */


Solution

  • The "hit" of the number 78 in the given example is explained by its position in the middle of the sorted list that is at (list.size()-1)/2, even if binary search in ascending order is applied incorrectly to the list sorted in reverse order.

    Searching for the other elements without taking into account the reverseOrder comparator is like a searching in the unsorted list, and therefore the results are undefined according to the documentation.

    Simple test to prove this:

    1. input data: even length = 4
    List<Integer> data = Arrays.asList(20, 98, 33, 78);
    data.sort(Collections.reverseOrder());
    System.out.println(data);
    
    for (int x : data) {
        int ix = Collections.binarySearch(data, x); // ascending is incorrect
        System.out.println("ix["+x+"]=" + ix);
        
        int ix2 = Collections.binarySearch(data, x, Collections.reverseOrder());
        System.out.println("reverse ix["+x+"]=" + ix2);
        System.out.println("----");
    }
    

    Output:

    [98, 78, 33, 20]
    ix[98]=-5
    reverse ix[98]=0
    ----
    ix[78]=1
    reverse ix[78]=1
    ----
    ix[33]=-1
    reverse ix[33]=2
    ----
    ix[20]=-1
    reverse ix[20]=3
    

    That is, all indexes for the reversed binary search are correct, while for the ascending binary search there's only one hit.

    1. input data: odd length List<Integer> data = Arrays.asList(20, 98, 33, 12, 78); Output
    [98, 78, 33, 20, 12]
    ix[98]=-6
    reverse ix[98]=0
    ----
    ix[78]=-6
    reverse ix[78]=1
    ----
    ix[33]=2
    reverse ix[33]=2
    ----
    ix[20]=-1
    reverse ix[20]=3
    ----
    ix[12]=-1
    reverse ix[12]=4
    

    Similarly, the middle element is luckily hit for ascending search, but the rest of the ascending search results are undefined.


    When searching for an element missing in the list, the binarySearch should return appropriate insertion point (which is negative), and appropriate comparator must be selected to provide good results:

    List<Integer> data = Arrays.asList(20, 98, 33, 12, 78);
    data.sort(Collections.reverseOrder());
    System.out.println(data);
    
    List<Integer> data = Arrays.asList(20, 98, 33, 12, 78);
    data.sort(Collections.reverseOrder());
    System.out.println(data);
    
    for (int i = 0, n = data.size(); i <= n; i++) {
        int x = i < n ? data.get(i) + 2 : data.get(i - 1) - 2;
        int ix = Collections.binarySearch(data, x);
        System.out.println("ix["+x+"]=" + ix);
        
        int ix2 = Collections.binarySearch(data, x, Collections.reverseOrder());
        System.out.println("reverse ix["+x+"]=" + ix2);
        System.out.println("----");
    }
    

    Output:

    [98, 78, 33, 20, 12]
    ix[100]=-6
    reverse ix[100]=-1
    ----
    ix[80]=-6
    reverse ix[80]=-2
    ----
    ix[35]=-6
    reverse ix[35]=-3
    ----
    ix[22]=-1
    reverse ix[22]=-4
    ----
    ix[14]=-1
    reverse ix[14]=-5
    ----
    ix[10]=-1
    reverse ix[10]=-6