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

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

 

示例 1:

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

 

思路:运用归并排序的特点,merge的过程中如果后面区间的数字比前面区间的数字要小的话,则可以利用下标关系一次计算出当前区间中的所有逆序对,从而优化时间复杂度,缺点就是归并排序会用到一个辅助数组,所以会增加空间复杂度,也算是一种用时间换取空间的思想。因为计算逆序对直接相减就可以算出来了,所以整体的时间复杂度仍然是排序过程的时间复杂度O(nlogn),空间复杂度为O(n)

 

代码:

class Solution {
public:
    int count = 0;
    vector<int> dummy;
    void merge(vector<int>& nums, int s1, int e1, int s2, int e2) {
        int index = s1;
        int pos1 = s1;
        int pos2 = s2;
        while (pos1 <= e1 && pos2 <= e2) {
            if (nums[pos1] <= nums[pos2]) {
                dummy[index++] = nums[pos1++];
            } else {
                dummy[index++] = nums[pos2++];
                count += e1 - pos1 + 1;
            }
        }
        while (pos1 <= e1) {
            dummy[index++] = nums[pos1++];
        }
        while (pos2 <= e2) {
            dummy[index++] = nums[pos2++];
        }
        for (int i = s1; i <= e2; ++i) {
            nums[i] = dummy[i];
        }
    }

    void func(vector<int>& nums, int s, int e) {
        if (s >= e) return;
        int mid = (s + e) / 2;
        func(nums, s, mid);
        func(nums, mid+1, e);
        merge(nums, s, mid, mid+1, e);
    }

    int reversePairs(vector<int>& nums) {
        int len = nums.size();
        dummy.resize(len);
        func(nums, 0, len - 1);
        return count;
    }
};

 

posted @ 2021-05-02 17:21  Veritas_des_Liberty  阅读(50)  评论(0编辑  收藏  举报