Merge Sort: Counting Inversions

  • + 0 comments

    Java Solution

        public static long countInversions(List<Integer> arr) {
            int size = arr.size();
            AtomicLong atomicLong = new AtomicLong(0L);
            
            mergeSort(arr, 0, size, atomicLong);
            
            return atomicLong.get();
        }
        
        private static void mergeSort(List<Integer> arr, int firstIndex, int lastIndex, AtomicLong atomicLong){
            if(firstIndex >= lastIndex){
                return;
            }
            final int mediumIndex = firstIndex + ((lastIndex - firstIndex) / 2);
            if(mediumIndex == firstIndex){
                return;
            }
            mergeSort(arr, firstIndex, mediumIndex, atomicLong);
            mergeSort(arr, mediumIndex, lastIndex, atomicLong);
            merge(arr, firstIndex, mediumIndex, lastIndex, atomicLong);
        }
        
        private static void merge(List<Integer> arr, int firstIndex, int mediumIndex, int lastIndex, AtomicLong atomicLong){
            final List<Integer> firstList = arr.subList(firstIndex, mediumIndex).stream().collect(Collectors.toList());
            final List<Integer> secondList = arr.subList(mediumIndex, lastIndex).stream().collect(Collectors.toList());
            
            final int firstSize = firstList.size();
            final int secondSize = secondList.size();
            
            if(firstSize == 0 || secondSize == 0){
                return;
            }
            
            int i = 0, j = 0, k = firstIndex;
            while(i<firstSize && j < secondSize){
                int first = firstList.get(i);
                int second = secondList.get(j);
                if(first <= second){
                    arr.set(k, first);
                    i++;
                }
                else{
                    arr.set(k, second);
                    j++;
                    atomicLong.addAndGet(firstSize-i);
                }
                k++;
            }
            
            while(i<firstSize){
                arr.set(k, firstList.get(i));
                i++;
                k++;
            }
            
            while(j < secondSize){
                arr.set(k, secondList.get(j));
                j++;
                k++;
            }
        }