剑指 Offer 51. 数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

 

示例 1:

输入: [7,5,6,4]
输出: 5

 

时间复杂度:O(NlogN),空间复杂度:O(N)

class Solution {
    public int reversePairs(int[] nums) {
        //写一个归并排序,在每次合并的时候对两组子数组进行计算逆序对,累加计数
        int len = nums.length;
        if(len<2)
            return 0;
        int[] temp = new int[len];
        int[] copy = new int[len];
        for(int i = 0;i<len;i++)
            copy[i] = nums[i];
        return process(copy,0,len-1,temp);
    }
    public int process(int[] nums,int left,int right,int[] temp)
    {
        if(left == right)
            return 0;
        int mid = left+(right-left)/2;
        int leftcount = process(nums,left,mid,temp);
        int rightcount = process(nums,mid+1,right,temp);
        if(nums[mid] <= nums[mid+1])
            return leftcount+rightcount;
        int mCount = merger(nums, left, mid, right, temp);
        return leftcount + rightcount +mCount;
    }
    public int merger(int[] nums,int left,int mid,int right,int[] temp)
    {
        for(int i = left;i<=right;i++)
            temp[i] = nums[i];
        int i = left;
        int j = mid+1;
        int count = 0;
        for(int k = left;k<=right;k++)
        {
            if(i == mid + 1)
            {
                nums[k] = temp[j];j++;
            }
            else if(j == right+1)
            {
                nums[k] = temp[i];i++;
            }
            else if(temp[i] <= temp[j])
            {
                nums[k] = temp[i];i++;
            }
            else
            {
                nums[k] = temp[j];j++;
                count+=mid-i+1;//归并排序过程中只多了这一句,移动j时记录前面有多少数组成逆序对
            }
        }
        return count;
    }
}

 

posted @ 2021-04-22 23:31  γGama  阅读(31)  评论(0编辑  收藏  举报