力扣【排序】:LCR 170. 交易逆序对的总数

  1. 题目描述:

在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个「交易逆序对」。请设计一个程序,输入一段时间内的股票交易记录 record,返回其中存在的「交易逆序对」总数。

  1. 算法思路:
  • 考虑逆序数的定义是在一个数组中有两个下标分别为i,j的元素,有i < j,nums[i] > nums[j]。对于一个数组nums,可以考虑分治思路,先计算左侧子数组的逆序数,再计算右侧子数组的逆序数,最后计算左侧对于右侧的逆序数即可。
  • 又想到,如果子数组分别有序,那么计算逆序数时如果nums[i] > nums[j],则从下标i开始到第一个子数组的最后一个元素内所有元素都可以和nums[j]构成逆序数,于是可以尝试在排序过程中计算逆序数,很显然这里使用归并排序是最合理的。
  • 到这里其实思路已经很清晰了,我们只需要将计算逆序数的过程嵌入到归并排序中即可,并且由于归并排序实际的排序过程是依靠merge实现的,所以只需要在merge时计算子数组的逆序数即可,按照分析只需要在nums[i] > nums[j]并且i < j时将mid - i + 1累加到一个逆序数统计变量即可。
  • 考虑当其中一个数组已经遍历结束的情况:如果左侧子数组遍历结束,那么右侧子数组剩余部分不会组成逆序数,因此不用计数,如果右侧子数组遍历结束,因为在遍历时必然出现过某个nums[i] > nums[j],所有的逆序数也已经被计算,所以剩余部分同样只需要正常排序即可。
  • 并且题目要求数组最大长度为50000,显然逆序数最大不会超过int上限,用等差数组求和可知。
  1. 代码:

时间复杂度:归并递归层次为 log n向上取整,每层递归都会遍历数组,O(n log n),n为数组长度
空间复杂度:递归深度为O(log n),辅助数组O(n),结果为O(n)

class Solution {
private:
    vector<int> tmp;
public:
    int reversePairs(vector<int>& record) {
        int size = record.size();
        if (size == 0) {
            return 0;
        }
        tmp.resize(size, 0);
        return MergeHelper(record, 0, size - 1);
    }

    int MergeHelper(vector<int> &record, int left, int right) {
        if (left == right) {
            return 0;
        }
        int mid = left + (right - left) / 2;
        int reverse_pairs = 0;
        reverse_pairs += MergeHelper(record, left, mid);
        reverse_pairs += MergeHelper(record, mid + 1, right);
        reverse_pairs += Merge(record, left, mid, right);

        return reverse_pairs;
    }

    int Merge(vector<int> &record, int left, int mid, int right) {
        int reverse_count = 0;
        for (int idx = left; idx <= right; ++idx) {
            tmp[idx] = record[idx];
        }

        int i = left;
        int j = mid + 1;
        for (int k = left; k <= right; ++k) {
            if (i == mid + 1) {
                record[k] = tmp[j];
                ++j;
            } else if (j == right + 1) {
                record[k] = tmp[i];
                ++i;
            } else if (tmp[i] > tmp[j]) {
                record[k] = tmp[j];
                reverse_count += mid - i + 1;
                ++j;
            } else if (tmp[i] <= tmp[j]) {
                record[k] = tmp[i];
                ++i;
            }
        }

        return reverse_count;
    }
};
posted @ 2026-08-21 19:34  lf123z  阅读(6)  评论(0)    收藏  举报