Data structure and algorithm -- reverse pair in array

Posted by dacs on Thu, 03 Feb 2022 06:50:10 +0100

  • Title: two numbers in the array. If a signature number is greater than the following array, the two numbers form a reverse order pair. Enter an array and find the total number of reverse pairs in this array.

  • Case: in the input array {7,5,6,4}, there are five pairs in reverse order, namely {7,6}, {7,5}, {7,4}, {6,4}, {5,4}

  • As described above, the simplest solution is to double cycle through the entire array, scan the first number, compare it with other numbers one by one, record the numbers smaller than him and add one, which is similar to a bubble sorting algorithm

  • The time complexity of the double cycle scheme is the same as that of the bubble sort, both of which are O(n2), so there should be a faster scheme

  • Scheme II:

    • Let's use {7,5,6,4} as a case study. Since we can't get the first one and compare it with the following list one by one, let's disassemble it to see if we can get a better scheme
    • We split the array from left to right into a single array of elements
    • Next, merge the adjacent sub arrays again and count the number of pairs in reverse order again
    • We use the following illustration
  • In the first step, we disassemble the array in half each time. We know that there are only one or two arrays left. Here, we use the best understood scheme to disassemble it into an independent one

  • The second step is to compare the adjacent pairs one by one. 7 < 5 is a reverse order pair. We should count +1, and combine the two independent arrays into an ordered array. Similarly, 6 and 4 are the same. We get two arrays, namely {7,5}, {6,4}

  • The third part then combines the two arrays and makes statistics. As shown in the figure below, when the left pointer points to 7 and the right points to 6, then left > right,

  • Because the two arrays are sequential at this time, the data pointed to by left is larger than all the numbers in the second array

  • Then the count superposition times should be the length of the second array, or the subscript size of the data pointed to by right + 1

  • Then move left, right, and put the larger number into the merged array

  • In the above steps, we first disassemble and then sort the sub arrays one by one according to our previous article: Data structure and algorithm - sorting algorithm summary (dynamic diagram demonstration) The idea of merging and sorting is the same

  • However, in our previous implementation, when merging, sorting and disassembly, we chose to disassemble into two, because this can reduce the number of recursion

  • At this time, we choose to disassemble into one because our purpose is to count the number of times. If we disassemble into two, we must make separate statistics when sorting the two separately, which is redundant logic

  • After the above analysis, there are the following codes:

/**
 * Find all pairs in reverse order in the array, for example:
 * {7,5,6,4} => 75,76,74,54,64
 * @author liaojiamin
 * @Date:Created in 14:50 2021/6/11
 */
public class InversePairs {
    public static Integer countInverse = 0;

    public static Integer[]  mergeSortFindPairs(Integer[] array){
        if(array == null || array.length <= 1){
            return array;
        }
        if(array.length < 2){
            return array;
        }
        Integer middle = array.length/2;
        Integer[] left = Arrays.copyOfRange(array, 0, middle);
        Integer[] right = Arrays.copyOfRange(array, middle, array.length);
        return merge(mergeSortFindPairs(left), mergeSortFindPairs(right));
    }

    public static Integer[] merge(Integer[] left, Integer[] right){
        Integer[] mergeArray = new Integer[left.length + right.length];
        Integer targetPosition = mergeArray.length-1;
        Integer leftPosition = left.length -1;
        Integer rightPosition = right.length -1;
        while (targetPosition >= 0){
            if(leftPosition >=0 && rightPosition >= 0){
                if(left[leftPosition] > right[rightPosition]){
                    countInverse+=(rightPosition+1);
                    mergeArray[targetPosition--] = left[leftPosition--];
                }else {
                    mergeArray[targetPosition--] = right[rightPosition--];
                }
            }else {
                if(leftPosition < 0){
                    while (rightPosition >= 0){
                        mergeArray[targetPosition--] = right[rightPosition--];
                    }
                }else {
                    while (leftPosition >= 0){
                        mergeArray[targetPosition--] = left[leftPosition--];
                    }
                }
            }
        }
        return mergeArray;
    }

    public static void main(String[] args) {
        Integer[] array = {1,3,44,22,31,4,0,32,14,16,32,9,4,7,23,555,12,123,456};
        array = mergeSortFindPairs(array);
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
        System.out.println(countInverse);
    }
}

Previous: data structures and algorithms - the first character that appears only once

Topics: Algorithm data structure