Counting inversions in an array

前端 未结 30 2623
死守一世寂寞
死守一世寂寞 2020-11-22 04:14

I\'m designing an algorithm to do the following: Given array A[1... n], for every i < j, find all inversion pairs such that A[i] > A[j]

30条回答
  •  清歌不尽
    2020-11-22 04:44

    Best optimized way will be to solve it through merge sort where will merging itself we can check how many inversions are required by comparing left and right array. Whenever element at left array is greater than element at right array, it will be inversion.

    Merge sort Approach :-

    Here is the code . Code is exact same as merge sort except code snippet under mergeToParent method where i am counting the inversion under else condition of (left[leftunPicked] < right[rightunPicked])

    public class TestInversionThruMergeSort {
        
        static int count =0;
    
        public static void main(String[] args) {
            int[] arr = {6, 9, 1, 14, 8, 12, 3, 2};
            
    
            partition(arr);
    
            for (int i = 0; i < arr.length; i++) {
    
                System.out.println(arr[i]);
            }
            
            System.out.println("inversions are "+count);
    
        }
    
        public static void partition(int[] arr) {
    
            if (arr.length > 1) {
    
                int mid = (arr.length) / 2;
                int[] left = null;
    
                if (mid > 0) {
                    left = new int[mid];
    
                    for (int i = 0; i < mid; i++) {
                        left[i] = arr[i];
                    }
                }
    
                int[] right = new int[arr.length - left.length];
    
                if ((arr.length - left.length) > 0) {
                    int j = 0;
                    for (int i = mid; i < arr.length; i++) {
                        right[j] = arr[i];
                        ++j;
                    }
                }
    
                partition(left);
                partition(right);
                mergeToParent(left, right, arr);
            }
    
        }
    
        public static void mergeToParent(int[] left, int[] right, int[] parent) {
    
            int leftunPicked = 0;
            int rightunPicked = 0;
            int parentIndex = -1;
    
            while (rightunPicked < right.length && leftunPicked < left.length) {
    
                if (left[leftunPicked] < right[rightunPicked]) {
                    parent[++parentIndex] = left[leftunPicked];
                    ++leftunPicked;
    
                } else {
                    count = count + left.length-leftunPicked;
                    if ((rightunPicked < right.length)) {
                        parent[++parentIndex] = right[rightunPicked];
                        ++rightunPicked;
                    }
                }
    
            }
    
            while (leftunPicked < left.length) {
                parent[++parentIndex] = left[leftunPicked];
                ++leftunPicked;
            }
    
            while (rightunPicked < right.length) {
                parent[++parentIndex] = right[rightunPicked];
                ++rightunPicked;
            }
    
        }
    
    }
    

    Another approach where we can compare the input array with sorted array:- This implementation of Diablo answer. Though this should not be preferred approach as removing the n elements from an array or list is log(n^2).

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;
    
    
    public class TestInversion {
    
        public static void main(String[] args) {
            
            Integer [] arr1 = {6, 9, 1, 14, 8, 12, 3, 2};
            
            List arr = new ArrayList(Arrays.asList(arr1));
            List sortArr = new ArrayList();
            
            for(int i=0;i iter = arr.iterator();
            
            while(iter.hasNext()){
                
                Integer el = (Integer)iter.next();
                int index = sortArr.indexOf(el);
                
                if(index+1 > 1){
                    inversion = inversion + ((index+1)-1);
                }
                
                //iter.remove();
                sortArr.remove(el);
                
            }
            
            System.out.println("Inversions are "+inversion);
            
            
            
    
        }
    
    
    }
    

提交回复
热议问题