逆序对问题可以用归并排序来解决。在归并排序的过程中,我们可以在合并两个有序数组的过程中,统计逆序对的个数。

具体来说,我们在合并两个有序数组时,先将它们分别按照从小到大的顺序排列,然后从前往后遍历这两个数组,每次取出较小的元素加入到合并后的数组中。如果取出的元素来自第一个数组,那么不会产生逆序对;如果来自第二个数组,那么产生的逆序对个数就是第一个数组中剩下的元素个数。

具体实现时,我们可以在归并排序的递归函数中添加一个参数,来记录逆序对的个数。每次合并两个有序数组时,将逆序对的个数加上第一个数组中剩余元素的个数即可。

时间复杂度为O(nlogn)。下面是代码实现:

#include <iostream>
#include <vector>

using namespace std;

int merge(vector<int>& nums, int left, int mid, int right, vector<int>& tmp) {
    int i = left, j = mid + 1, k = 0;
    int count = 0;
    while (i <= mid && j <= right) {
        if (nums[i] <= nums[j]) {
            tmp[k++] = nums[i++];
        } else {
            tmp[k++] = nums[j++];
            count += mid - i + 1;
        }
    }
    while (i <= mid) tmp[k++] = nums[i++];
    while (j <= right) tmp[k++] = nums[j++];
    for (i = 0; i < k; i++) {
        nums[left + i] = tmp[i];
    }
    return count;
}

int mergeSort(vector<int>& nums, int left, int right, vector<int>& tmp) {
    if (left >= right) return 0;
    int mid = left + (right - left) / 2;
    int count = mergeSort(nums, left, mid, tmp) + mergeSort(nums, mid + 1, right, tmp);
    count += merge(nums, left, mid, right, tmp);
    return count;
}

int reversePairs(vector<int>& nums) {
    int n = nums.size();
    vector<int> tmp(n);
    return mergeSort(nums, 0, n - 1, tmp);
}

int main() {
    vector<int> nums = {7, 5, 6, 4};
    cout << reversePairs(nums) << endl; // expect 5
    return 0;
}
P1750 求逆序对

原文地址: https://www.cveoy.top/t/topic/b7wy 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录