剑指offer(51)

剑指offer(51)

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

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

示例 1:

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

限制:

0 <= 数组长度 <= 50000

归并排序:

​ 本题统计逆序对,我们可以在归并排序的过程中去统计,nums数组的逆序对的数量是两边的子序列逆序对数量加上左边子序列比右边子序列大的逆序对数量。

class Solution {
public:
    int reversePairs(vector<int>& nums) {
        //在归并排序过程中去统计逆序对
        vector<int>temp(nums.size());
        return mergeSort(0,nums.size()-1,nums,temp);//归并排序返回nums数组中的逆序对数
    }
    int mergeSort(int l,int r,vector<int>&nums,vector<int>&temp){
        //终止条件
        if(l>=r)return 0;
        int m=l+(r-l)/2;
        //nums逆序对数量等于两边的子序列的逆序对数量加上左边比右边大的数量
        int res=mergeSort(l,m,nums,temp)+mergeSort(m+1,r,nums,temp);
        //保存归并排序前的nums数组位置
        int i=l;int j=m+1;
        for(int k=l;k<=r;k++){
            temp[k]=nums[k];
        }
        //开始合并 小的放前面 
        for(int k=l;k<=r;k++){
            if(i==m+1){//如果第一个子序列走完了 那么后面的就都是第二个子序列
                nums[k]=temp[j];
                j++;
            }
            //如果第二个子序列走完了 或者 左边子序列值小于右边子序列值 都是放左边的子序列
            else if(j==r+1||temp[i]<=temp[j]){
                nums[k]=temp[i];
                i++;
            }else{
              //如果左边子序列值大于右边子序列
              //就出现了逆序对
              //出现了多少对呢?左边子序列是有序的所以左边子序列后面的值都能构成子序列 即m-i+1;
                nums[k]=temp[j];
                j++;
                res+=m-i+1;
            }
        }
        return res;
    }
};
posted @ 2022-05-05 09:50  BailanZ  阅读(18)  评论(0编辑  收藏  举报