Counting inversions in an array

前端 未结 30 1993
死守一世寂寞
死守一世寂寞 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:51

    Maximum number of inversions possible for a list of size n could be generalized by an expression:

    maxPossibleInversions = (n * (n-1) ) / 2
    

    So for an array of size 6 maximum possible inversions will equal 15.

    To achieve a complexity of n logn we could piggy back the inversion algorithm on merge sort.

    Here are the generalized steps:

    • Split the array into two
    • Call the mergeSort routine. If the element in the left subarray is greater than the element in right sub array make inversionCount += leftSubArray.length

    That's it!

    This is a simple example, I made using Javascript:

    var arr = [6,5,4,3,2,1]; // Sample input array
    
    var inversionCount = 0;
    
    function mergeSort(arr) {
        if(arr.length == 1)
            return arr;
    
        if(arr.length > 1) {
            let breakpoint = Math.ceil((arr.length/2));
            // Left list starts with 0, breakpoint-1
            let leftList = arr.slice(0,breakpoint);
            // Right list starts with breakpoint, length-1
            let rightList = arr.slice(breakpoint,arr.length);
    
            // Make a recursive call
            leftList = mergeSort(leftList);
            rightList = mergeSort(rightList);
    
            var a = merge(leftList,rightList);
            return a;
        }
    }
    
    function merge(leftList,rightList) {
        let result = [];
        while(leftList.length && rightList.length) {
            /**
             * The shift() method removes the first element from an array
             * and returns that element. This method changes the length
             * of the array.
             */
            if(leftList[0] <= rightList[0]) {
                result.push(leftList.shift());
            }else{
                inversionCount += leftList.length;
                result.push(rightList.shift());
            }
        }
    
        while(leftList.length)
            result.push(leftList.shift());
    
        while(rightList.length)
            result.push(rightList.shift());
    
        console.log(result);
        return result;
    }
    
    mergeSort(arr);
    console.log('Number of inversions: ' + inversionCount);
    

提交回复
热议问题