【Offer】[51] 【数组中的逆序对】

题目描述

  在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如,在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7, 6)、(7,5)、(7,4)、(6, 4)和(5, 4)。

牛客网刷题地址

思路分析

  利用归并排序的思想:先将数组分解成为n个长度为1的子数组,然后进行两两合并同时排好顺序。在对两个子区域合并排序时,记左边区域(下标为start~mid)的指针为i,右边区域(下标为mid+1~end)的指针为j,两个指针都指向该区域内最大的数字,排序时:

  1. 如果i指向的数字大于j指向的数字,说明:逆序对有j-mid个,我们把i指向的数字放入临时创建的排序数组中,然后令i-1,指向该区域前一个数字,继续进行排序;
  2. 如果i指向的数字小于等于j指向的数字,说明暂时不存在逆序对,将j指向的数字放入临时创建的排序数组中,然后令j-1,指向该区域前一个数字,继续进行排序;
  3. 某一子区域数字都放入排序数组后,将另一个子区域剩下的数字放入排序数组中,完成排序;
  4. 最后将排序好的数字按顺序赋值给原始数组的两个子区域,以便合并后的区域与别的区域合并。

测试用例

  1. 功能测试:输入未经排序的数组、递增排序的数组、递减排序的数组:输入的数组中包含重复的数字。
  2. 边界值测试:输入的数组中只有两个数字;输入的数组中只有一个数字。
  3. 特殊输入测试:表示数组的指针为nullptr指针。

Java代码

public class Offer051 {
    public static void main(String[] args) {
        test1();
        test2();
        test3();

    }

    public static int inversePairs(int[] array) {
        return Solution1(array);
    }

    private static int Solution1(int[] array) {
        if (array == null || array.length <= 0)
            return 0;
        int count = getCount(array, 0, array.length - 1);
        return count;
    }

    private static int getCount(int[] array,int start,int end){
        if(start>=end)
            return 0;
        int mid=(end+start)>>1;
        int left=getCount(array,start,mid)%1000000007;
        int right=getCount(array,mid+1,end)%1000000007;
         
        //合并
        int count=0;
        int i=mid; //左边区域的指针
        int j=end; //右边区域的指针
        int[] temp= new int[end-start+1];  //临时区域
        int k=end-start; //临时区域的指针
        while(i>=start && j>=mid+1){
            if(array[i]>array[j]){
                count+=(j-mid);
                temp[k--]=array[i--];
                if(count>=1000000007)//数值过大求余
                {
                    count%=1000000007;
                }
            }else{
                temp[k--]=array[j--];
            }
        }
        while(i>=start)
            temp[k--]=array[i--];
        while(j>=mid+1)
            temp[k--]=array[j--];
        for(k=0;k<temp.length;k++)
            array[k+start]=temp[k];
         
        return (count+left+right)%1000000007;
    }

    private static void test1() {

    }

    private static void test2() {

    }

    private static void test3() {

    }
}

代码链接

剑指Offer代码-Java

原文地址:https://www.cnblogs.com/haoworld/p/offer51-shu-zu-zhong-de-ni-xu-dui.html