package com.anuragkapur.misc; /** * Count number of split inversions in an array * * @author anuragkapur */ public class CountInversions { static int a[] = {3,5,1,2,4,6}; /** * Assumes the 2 parts of the array are sorted, and merges them. While merging, count split inversions * * @param start * @param end * @param leftStart * @param leftEnd * @param rightStart * @param rightEnd * @return */ public static int countSplitInversionsAndMerge(int start, int end, int leftStart, int leftEnd, int rightStart, int rightEnd) { int subArray1[] = new int[leftEnd - leftStart + 1]; int subArray2[] = new int[rightEnd - rightStart + 1]; int count = 0; for (int i = leftStart; i <= leftEnd; i++) { subArray1[count++] = a[i]; } count = 0; for (int i = rightStart; i <= rightEnd; i++) { subArray2[count++] = a[i]; } // merge and count inversions int leftPointer = 0, rightPointer = 0, inversions = 0; for (int i = start; i <= end; i++) { if(leftPointer >= subArray1.length) { a[i] = subArray2[rightPointer++]; }else if(rightPointer >= subArray2.length) { a[i] = subArray1[leftPointer++]; }else if (subArray1[leftPointer] <= subArray2[rightPointer]) { a[i] = subArray1[leftPointer++]; }else if(subArray1[leftPointer] > subArray2[rightPointer]) { for (int j = leftPointer; j < subArray1.length; j++) { System.out.println(subArray1[j] + "," + subArray2[rightPointer]); } a[i] = subArray2[rightPointer++]; inversions = inversions + subArray1.length - leftPointer; } } return inversions; } /** * Recursive method to count left and right inversions * * @param start * @param end * @return */ public static int countInversionsAndSort(int start, int end) { System.out.println("start :: " + start + " end :: " + end); if(end - start == 1) { // two elements in array, just sort them and return if this is an inversion if (a[start] > a[end]) { int temp = a[start]; a[start] = a[end]; a[end] = temp; return 1; }else { return 0; } }else if(end == start) { // one element in array, no sorting required, can be a left / right inversion return 0; }else { int leftStart = start; int leftEnd = ((end - start) / 2 ) + start; int rightStart = ((end - start) / 2 ) + start +1; int rightEnd = end; int leftInversions = countInversionsAndSort(leftStart, leftEnd); int rightInversions = countInversionsAndSort(rightStart, rightEnd); int splitInversions = countSplitInversionsAndMerge(start, end, leftStart, leftEnd, rightStart, rightEnd); return leftInversions + rightInversions + splitInversions; } } /** * @param args */ public static void main(String[] args) { System.out.println(countInversionsAndSort(0, a.length-1)); } }