javaalgorithmsortingmergesort

merge sort algorithm implemented in java giving ArrayIndexOutOfBound Exception


ive rewritten it a hundred times, i keep getting an IndexOutOfBound exception. It may be an issue if the first for loop that fills in the left array, but im not sure how to change the logic.

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10 at mergeSortWithTwist.merge(mergeSortWithTwist.java:57)

i don't know what else to do, any help is appreciated !

public static void merge(int[] inputArr, int p, int q, int r) {

       int n1 = q-p+1;
       int n2 = r-q;
       int[] leftHalf = new int[n1];
       int[] rightHalf = new int[n2];

       for(int i = 0; i < n1; i++)
           leftHalf[i] = inputArr[p+i-1];

       for(int i = 0; i < n2; i++)
           rightHalf[i] = inputArr[q+i];

       leftHalf[n1+1] = Integer.MAX_VALUE;
       rightHalf[n2+1] = Integer.MAX_VALUE;

       int i = 0;
       int j = 0;
   

       for(int k = 0; k < r; k++) {
           if(leftHalf[i] <= rightHalf[j]){
               inputArr[k] = leftHalf[i];
               i++;
           }
           else {
               inputArr[k] = rightHalf[j];
               j++;
           }
       }

   }

    public static void merge_sort(int[] inputArr, int p, int r) {
        if(p<r) {
            int q = (p + r) / 2;
            merge_sort(inputArr,p,q);
            merge_sort(inputArr,q+1,r);
            merge(inputArr,p,q,r);
        }
    }


Solution

  • There are several issues:

    Here is your merge function with corrections for the above issues:

        public static void merge(int[] inputArr, int p, int q, int r) {
            int n1 = q-p+1;
            int n2 = r-q;
            int[] leftHalf = new int[n1 + 1]; // Corrected: need one extra entry
            int[] rightHalf = new int[n2 + 1]; // Corrected: need one extra entry
            for(int i = 0; i < n1; i++)
                leftHalf[i] = inputArr[p+i]; // Corrected: start at inputArr[p]
            for(int i = 0; i < n2; i++)
                rightHalf[i] = inputArr[q+1+i]; // Corrected: start at inputArr[q+1]
            leftHalf[n1] = Integer.MAX_VALUE; // Corrected: use last slot
            rightHalf[n2] = Integer.MAX_VALUE; // Corrected: use last slot
            int i = 0;
            int j = 0;
            for(int k = p; k <= r; k++) { // Corrected: start at p, end at r
                if(leftHalf[i] <= rightHalf[j]){
                    inputArr[k] = leftHalf[i];
                    i++;
                }
                else {
                    inputArr[k] = rightHalf[j];
                    j++;
                }
            }
        }
    

    Note that all these bugs can be found by meticulous debugging: stepping through the code, setting breakpoints, inspecting variables, possibly printing them.

    Using MAX_VALUE?

    As noted in comments: although the use of MAX_VALUE as "stopper" value simplifies the merge part of your code a bit, this requires that the input will not have this value as actual data value. If MAX_VALUE is considered a valid data value (and why not?), you cannot really use this shortcut, and would better do it without:

        public static void merge(int[] inputArr, int p, int q, int r) {
            int n1 = q-p+1;
            int n2 = r-q;
            int[] leftHalf = new int[n1];
            int[] rightHalf = new int[n2];
            for(int i = 0; i < n1; i++)
                leftHalf[i] = inputArr[p+i];
            for(int i = 0; i < n2; i++)
                rightHalf[i] = inputArr[q+1+i];
            int i = 0;
            int j = 0;
            for(int k = p; k <= r; k++) {
                // Boundary checks instead of relying on MAX_VALUE:
                if(i < n1 && (j == n2 || leftHalf[i] <= rightHalf[j])) {
                    inputArr[k] = leftHalf[i];
                    i++;
                }
                else {
                    inputArr[k] = rightHalf[j];
                    j++;
                }
            }
        }