Leetcode: 剑指 Offer 51. 数组中的逆序对  [Hard]

114 阅读1分钟

这个题主要用到了排序算法中的 mergeSort, 通过 mergeSort(分治法)过程中来发现我们的逆序对



class Solution {
public:
    int reversePairs(vector<int>& nums) {
        vector<int> temp(nums.size());
        return mergeSort(0, nums.size()-1, nums, temp); 
    }

    int mergeSort(int l, int r, vector<int>& nums, vector<int>& temp){
        // 先写出递归的结束条件, 当左数组与右数组是一个的时候, 停止, 返回0, 因为不存在逆序对
        if(l>=r) return 0;
        // 分, 我们需要找到 中间点(分点)
        int m = (l + r)/2;
        // 记录左子数组的后代的res总和,  记录右子数组的后代的res总和(只包括后代, 不包括 左右子数组)
        int res = mergeSort(l, m, nums, temp) + mergeSort(m+1,  r, nums, temp);
        // 在 mergeSort(从小到大, 左子数组和右子树组都是排好序的) 该层的 左数组 与 右数组 顺便统计下 该层的 res
        // 1. 首先我们需要先复制copy一份temp, 用来存放原始值, 而nums则是排序好之后的
        for(int k= l; k<=r; k++){
            temp[k] = nums[k];
        }
        // 2. 建立左右子数组的两个指针 i ,j 分别指向左右子数组的开头
        int i = l;
        int j = m+1;
        for(int k=l; k<=r; k++) {
            // 左右merge的时候, 如果左子数组都已经被添加完了, 只有右子数组剩余
            if(i==m+1){
                nums[k] = temp [j];
                j++;
            }
            // 左右merge的时候, 如果右子数组都已经被添加完了, 只有左子数组剩余,那么全加入,没得可比了
            // 或者, 左子数组的值 < 右子数组的值 => 不够成逆序对
            else if(j == r+1 || temp[i]<=temp[j]){
                nums[k] = temp[i];
                i++;
            }
            // 左子数组的值 > 右子数组的值, mergeSort 右子树组的值的时候(同时记录一下res, 因为右边的这个值与当前剩余的左子树都构成了逆序对)
            else{
                nums[k] = temp[j];
                j++;
                res += m -i +1;
            }
        }
        return res;
    }
};