当前位置: 首页 > article >正文

(每日一道算法题)交易逆序对的总数

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个「交易逆序对」。请设计一个程序,输入一段时间内的股票交易记录 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

暴力解法的问题

最直观的解法是双重循环遍历所有可能的 (i, j) 组合,统计满足 i < j 且 record[i] > record[j] 的对数。这种方法的时间复杂度为 O(n²),当数组长度较大(例如 50000)时,显然无法高效处理。

归并排序解法

归并排序的分治思想天然适合解决逆序对问题。在归并排序的合并阶段,可以高效地统计逆序对数目。

归并排序合并阶段的统计逻辑
  1. 分治:将数组分为左右两部分,递归处理左右子数组。
  2. 合并:合并两个有序子数组时,若左子数组的当前元素大于右子数组的当前元素,则左子数组中剩余的所有元素均与该右子数组元素构成逆序对。
  3. 累加:每次发现左子数组元素大于右子数组元素时,累加左子数组剩余元素的个数到总逆序对数目。
代码实现
class Solution {
    int[] tmp; // 临时数组用于归并排序
    int ret;   // 统计逆序对总数

    public int reversePairs(int[] nums) {
        tmp = new int[nums.length];
        mergesort(nums, 0, nums.length - 1);
        return ret;
    }

    private void mergesort(int[] nums, int left, int right) {
        if (left >= right) return;
        int mid = left + (right - left) / 2;
        // 递归处理左右子数组
        mergesort(nums, left, mid);
        mergesort(nums, mid + 1, right);
        // 若左子数组最大值 <= 右子数组最小值,无需合并
        if (nums[mid] <= nums[mid + 1]) return;
        // 合并两个有序子数组,并统计逆序对
        int cur1 = left, cur2 = mid + 1, i = 0;
        while (cur1 <= mid && cur2 <= right) {
            if (nums[cur1] <= nums[cur2]) {
                tmp[i++] = nums[cur1++];
            } else {
                ret += mid - cur1 + 1; // 统计逆序对数目
                tmp[i++] = nums[cur2++];
            }
        }
        // 处理剩余元素
        while (cur1 <= mid) tmp[i++] = nums[cur1++];
        while (cur2 <= right) tmp[i++] = nums[cur2++];
        // 将排序后的临时数组复制回原数组
        for (int j = left; j <= right; j++) {
            nums[j] = tmp[j - left];
        }
    }
}

示例分析

以示例 record = [9, 7, 5, 4, 6] 为例,归并排序的合并过程如下:

  1. 初始分割:数组分为左 [9,7,5] 和右 [4,6]
  2. 处理左子数组
    • 分割为 [9,7] 和 [5],合并时 9 > 7 产生 1 个逆序对。
    • 合并 [7,9] 和 [5]7 > 5 产生 2 个逆序对。
  3. 处理右子数组:合并 [4] 和 [6],无逆序对。
  4. 合并左右子数组
    • 比较 5 和 4,产生 3 个逆序对。
    • 比较 5 和 6,无逆序对。
    • 比较 7 和 6,产生 2 个逆序对。
    • 累计总逆序对数目为 1 + 2 + 3 + 2 = 8。

复杂度分析

  • 时间复杂度:O(n log n),归并排序的时间复杂度。
  • 空间复杂度:O(n),用于归并排序的临时数组。

通过归并排序的分治策略,可以在高效排序的同时统计逆序对数目,从而快速解决大规模数据的逆序对问题。


http://www.kler.cn/a/595403.html

相关文章:

  • 微信小程序使用状态管理 - mobx-miniprogram
  • [特殊字符] 2025蓝桥杯备赛Day7——B2117 整理药名
  • H3C网络设备基础之单臂路由技术
  • Go语言反射机制详解
  • 如何从CentOS 7升级到8?CentOS 8最新安装教程
  • 从技术架构视角解析衡石可视化产品的灵活性与用户体验优化
  • 车辆模型——运动学模型
  • Wpf Avalonia-实现中英文切换工程
  • 【初探数据结构】堆的应用实例(堆排序与Top问题)
  • K8S学习之基础四十一:Prometheus基于Pushgateway采集数据
  • 基于Azure云平台构建实时数据仓库
  • 大模型的微调技术(高效微调原理篇)
  • 《鸟哥的Linux私房菜基础篇》---5 vim 程序编辑器
  • 【工具分享】vscode+deepseek的接入与使用
  • java项目之基于ssm的旅游论坛(源码+文档)
  • ScopeSentry(自动化信息收集工具)搭建[Linux]
  • struts1+struts2项目兼容升级到了spring boot 2.7
  • AI Agent系列(七) -思维链(Chain of Thought,CoT)
  • 5.特征工程与维度降维实践指南——Python数据挖掘代码实践
  • AI 护航:企业数据治理的安全蜕变