There are several bugs in the merge part of your program (not including the one that NPE showed), first:
int mid = (last-first)/2;
it should be:
int mid = (last+first)/2;
Secondly, the three for-loop ends at the end work independently - but you should only work on the rest of either a1 / a2.
I implemented it a little differently - perhaps this will help explain the second error:
public static void mergeSort(int[] arr, int start, int end){ if(start == end) return; // now the recursive calls: // divide the arr: int middle = (end+start)/2; mergeSort(arr, start, middle); mergeSort(arr, middle+1, end); // now merge (conquer) merge(arr, start, end, middle); } private static void merge(int[] arr, int start, int end, int middle) { int[] sorted = new int[end-start+1]; for(int i=start,j=middle+1,index=0; index < sorted.length;){ if(j<=end && arr[i] > arr[j]){ sorted[index] = arr[j]; j++; index++; } else if (i<=middle){ sorted[index] = arr[i]; i++; index++; } else{ sorted[index] = arr[j]; j++; index++; } } // now copy "sorted" to original array for(int i=start,j=0; i<=end; i++,j++){ arr[i] = sorted[j]; } } public static void main(String...args){ int[] arr = {4,2,9,6,2,8,1,9,10,15,12,11}; mergeSort(arr, 0, arr.length - 1); for(int i=0; i<arr.length; i++){ System.out.print(arr[i]+" "); } }