• 每日OJ题_分治归并②_力扣LCR 170. 交易逆序对的总数


    目录

    力扣LCR 170. 交易逆序对的总数

    解析代码1

    解析代码2


    力扣LCR 170. 交易逆序对的总数

    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 <= record.length <= 50000

    1. class Solution {
    2. public:
    3. int reversePairs(vector<int>& record) {
    4. };

    解析代码1

            用归并排序求逆序数是很经典的方法,主要就是在归并排序的合并过程中统计出逆序对的数量,也就是在合并两个有序序列的过程中,能够快速求出逆序对的数量。

    如果将数组从中间划分成两个部分,那么我们可以将逆序对产生方式划分成三组:

    • 逆序对中两个元素:全部从左数组中选择。
    • 逆序对中两个元素:全部从右数组中选择。
    • 逆序对中两个元素:一个选左数组另一个选右数组。

            根据排列组合的分类相加原理,三种情况下产生的逆序对的总和,正好等于总的逆序对数量。而这个思路正好匹配归并排序的过程:

    • 先排序左数组。
    • 再排序右数组。
    • 左数组和右数组合二为一。

            因此,我们可以利用归并排序的过程,先求出左半数组中逆序对的数量,再求出右半数组中逆序对的数量,最后求出⼀个选择左边,另⼀个选择右边情况下逆序对的数量,三者相加即可。

    1. class Solution {
    2. vector<int> tmp;
    3. public:
    4. int reversePairs(vector<int>& record) {
    5. tmp.resize(record.size());
    6. return mergeSortCnt(record, 0, record.size() - 1);
    7. }
    8. int mergeSortCnt(vector<int>& arr, int left, int right)
    9. { // 解法一:找出该数之前,有多少个数比我大 -> 升序
    10. if(left >= right)
    11. return 0;
    12. int ret = 0, mid = (left + right) >> 1;
    13. // 左边逆序对的个数+排序 + 右边逆序对的个数+排序
    14. ret += mergeSortCnt(arr, left, mid);
    15. ret += mergeSortCnt(arr, mid + 1, right);
    16. // 一左一右逆序对的个数
    17. int cur1 = left, cur2 = mid + 1, i = 0;
    18. while(cur1 <= mid && cur2 <= right)
    19. {
    20. if(arr[cur1] > arr[cur2])
    21. { // 此时cur2后面的都是比cur1小的
    22. ret += mid - cur1 + 1;
    23. tmp[i++] = arr[cur2++];
    24. }
    25. else
    26. {
    27. tmp[i++] = arr[cur1++];
    28. }
    29. }
    30. // 处理排序
    31. while (cur1 <= mid)
    32. tmp[i++] = arr[cur1++];
    33. while (cur2 <= right)
    34. tmp[i++] = arr[cur2++];
    35. for (int j = left; j <= right; j++)
    36. arr[j] = tmp[j - left];
    37. return ret;
    38. }
    39. };

    解析代码2

    在代码一的基础上可以选择找出该数之前,有多少个数比我小 -> 降序:

    1. class Solution {
    2. vector<int> tmp;
    3. public:
    4. int reversePairs(vector<int>& record) {
    5. tmp.resize(record.size());
    6. return mergeSortCnt(record, 0, record.size() - 1);
    7. }
    8. int mergeSortCnt(vector<int>& arr, int left, int right)
    9. { // 解法二:找出该数之前,有多少个数比我小 -> 降序
    10. if(left >= right)
    11. return 0;
    12. int ret = 0, mid = (left + right) >> 1;
    13. // 左边逆序对的个数+排序 + 右边逆序对的个数+排序
    14. ret += mergeSortCnt(arr, left, mid);
    15. ret += mergeSortCnt(arr, mid + 1, right);
    16. // 一左一右逆序对的个数
    17. int cur1 = left, cur2 = mid + 1, i = 0;
    18. while(cur1 <= mid && cur2 <= right)
    19. {
    20. if(arr[cur1] > arr[cur2])
    21. { // 此时cur2后面的都是比cur1小的
    22. // ret += mid - cur1 + 1;
    23. // tmp[i++] = arr[cur2++];
    24. ret += right - cur2 + 1;
    25. tmp[i++] = arr[cur1++]; // 降序
    26. }
    27. else
    28. {
    29. // tmp[i++] = arr[cur1++];
    30. tmp[i++] = arr[cur2++]; // 降序
    31. }
    32. }
    33. // 处理排序
    34. while (cur1 <= mid)
    35. tmp[i++] = arr[cur1++];
    36. while (cur2 <= right)
    37. tmp[i++] = arr[cur2++];
    38. for (int j = left; j <= right; j++)
    39. arr[j] = tmp[j - left];
    40. return ret;
    41. }
    42. };
  • 相关阅读:
    用 ChatGPT 做一个 Chrome 扩展 | 京东云技术团队
    这八种情形,专利优先审查一律不予推荐!
    【Cherno的C++视频】Continuous integration in C++
    Linux下的打包(tar)、压缩(gzip / bzip2)
    使用ION-SFU和媒体设备在Golang中构建一个WebRTC视频和音频广播器
    ThinkPHP 集成 jwt 技术 token 验证
    golang pprof
    docker部署JAVA项目
    李迟2022年11月工作生活总结
    SAP ADM100-1.2之系统登录过程(ABAP)
  • 原文地址:https://blog.csdn.net/GRrtx/article/details/136383138