Fork me on GitHub

困难-剑指offer51-数组中的逆序对

 

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

示例 1:

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

限制:

0 <= 数组长度 <= 50000

 

线段树的思路还没看,先写归并排序

 

将大数组递归至小数组开始合并,在合并left数组和right数组时,此时两数组内部的逆序对已经计算过,只需计算两数组间的逆序对,因此合并left数组时,无需加值,而合并right数组时加上left数组中为合并的元素个数即可。

class Solution {
    public int reversePairs(int[] nums) {
        int len = nums.length;
        if(len<2) return 0;
        int[] copy = new int[len];
        for(int i=0; i<len; i++)
            copy[i] = nums[i];
        int[] temp = new int[len];
        return reversePairs(nums,0,len-1,temp);
    }
    public int reversePairs(int[] nums, int left, int right, int[] temp) {
        if(left == right) return 0;
        int mid = left + (right - left) / 2;
        int leftPairs = reversePairs(nums,left,mid,temp);
        int rightPairs = reversePairs(nums,mid+1, right, temp);
        if(nums[mid]<=nums[mid+1]) return leftPairs + rightPairs;
        int crossPairs = mergeAndCount(nums,left,mid,right,temp);
        return leftPairs + rightPairs + crossPairs;
    }
    public int mergeAndCount(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);
            }
        }
        return count;
    }
}

 

posted @ 2020-12-13 14:13  Faded828x  阅读(92)  评论(0编辑  收藏  举报