[LeetCode][LCR170]交易逆序对的总数

题目

LCR 170. 交易逆序对的总数

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

  • 示例 1:

输入:record = [9, 7, 5, 4, 6]
输出:8
解释:交易中的逆序对为 (9, 7), (9, 5), (9, 4), (9, 6), (7, 5), (7, 4), (7, 6), (5, 4)。

  • 限制:
    0 <= records.length <= 50000

思考

  1. 这题很容易想到用暴力解法,但是由于数组过长,所以此时间复杂度是不能接受的
  2. 第二种想法是从后往前进行统计,将统计过的数字放入大顶堆,当前数字比大顶堆堆顶元素大时,则有堆大小即为逆序对数量,不断遍历。但是有可能当前数字比堆顶元素小,此时就要依次弹出堆顶元素进行比较,这样会提高复杂度
  3. K 神利用了归并排序的思想:在合并的时候,实际上是两个递增序列的合并,所以当左边序列的一个元素大于右边序列的一个元素时,左边序列这个元素及其后面的所有元素都大于右边的这个元素,在合并的过程中顺便进行了逆序对的统计,时间复杂度为 O(NlogN)

解法1:归并——整体的临时数组

作者:Krahets
链接:https://leetcode.cn/leetbook/read/illustration-of-algorithm/o53yjd/

在这里插入图片描述

class Solution {
public:
    int reversePairs(vector<int>& record) {
        vector<int> tmp(record.size());
        return mergeSort(0, record.size() - 1, record, tmp);
    }
private:
    int mergeSort(int l, int r, vector<int>& record, vector<int>& tmp) {
        // 终止条件
        if (l >= r) return 0;
        // 递归划分
        int m = (l + r) / 2;
        int res = mergeSort(l, m, record, tmp) + mergeSort(m + 1, r, record, tmp);
        // 合并阶段
        int i = l, j = m + 1;
        for (int k = l; k <= r; k++)
            tmp[k] = record[k];
        for (int k = l; k <= r; k++) {
            if (i == m + 1)
                record[k] = tmp[j++];
            else if (j == r + 1 || tmp[i] <= tmp[j])
                record[k] = tmp[i++];
            else {
                record[k] = tmp[j++];
                res += m - i + 1; // 统计逆序对
            }
        }
        return res;
    }
};

解法2:归并——局部变量临时数组

此处利用了一般归并排序的写法,使用一局部变量临时数组,相对于解法1 较慢。
归并排序

class Solution {
public:
    int reversePairs(vector<int>& record) {
        return mergeSort(record, 0, record.size()-1);
    }
    int mergeSort(vector<int>& nums, int low, int high) {
        if(low>=high) return 0;
        int mid=(high+low)/2;
        //分
        int res=mergeSort(nums, low, mid) + mergeSort(nums, mid+1, high);
        //治
        vector<int> temp;
        temp.assign(nums.begin()+low, nums.begin()+high+1);
        int i=0, j=mid-low+1;
        for(int x=low; x<=high; ++x){
            if(i==mid-low+1) nums[x]=temp[j++];
            else if(j==high-low+1 || temp[j]>=temp[i]) nums[x]=temp[i++];
            else{
                nums[x]=temp[j++];
                //当左边的有序序列遍历到的数大于右边有序序列遍历到的数,则左边序列遍历到的数之后都大于右边序列遍历到的这个数
                res += mid-(i+low)+1;            
            } 
        }
        return res;
    }
};

相关推荐

  1. Acwing---788.数量

    2024-03-25 18:46:06       32 阅读
  2. 2024-03-25 18:46:06       27 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-25 18:46:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-25 18:46:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-25 18:46:06       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-25 18:46:06       20 阅读

热门阅读

  1. sqllabs1-7sql注入

    2024-03-25 18:46:06       16 阅读
  2. c++ STL 之映射—— map 详解

    2024-03-25 18:46:06       20 阅读
  3. MTU网络大小

    2024-03-25 18:46:06       20 阅读
  4. C# 实体转换

    2024-03-25 18:46:06       18 阅读
  5. Linux常用命令

    2024-03-25 18:46:06       17 阅读
  6. MySQL知识总结

    2024-03-25 18:46:06       19 阅读
  7. 《大厂面试模拟(免费) - C++工程方向》

    2024-03-25 18:46:06       18 阅读
  8. C++ IDisposable 接口抽象类实现

    2024-03-25 18:46:06       21 阅读
  9. 计算机网络参考模型(OSI和TCP/IP 网络模型)

    2024-03-25 18:46:06       17 阅读
  10. 什么是原型链

    2024-03-25 18:46:06       19 阅读
  11. AD实用设置教程

    2024-03-25 18:46:06       16 阅读
  12. C语言 指针综合应用 ( 高阶应用 )

    2024-03-25 18:46:06       19 阅读
  13. Redis面试题

    2024-03-25 18:46:06       18 阅读