LCR 170. 交易逆序对的总数(C语言+分治递归)

博客围绕股票交易逆序对问题展开,给出题目,即输入股票交易记录返回逆序对总数。介绍使用分治和归并排序方法计算逆序对数量的思路,分析各阶段时间复杂度,最终总时间复杂度为O(nlogn),还给出了LeetCode相关题目链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 题目

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

2. 输入输出样例

        示例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

3. 实现思路

         使用分治和归并排序的方法来计算整数数组中的逆序对数量,主要的思路是:

        (1)将数组分解为两个子数组;

        (2)递归地计算每个子数组的逆序对数量;

        (3)在归并的过程中,统计两个子数组之间的逆序对数量,并将子数组合并成一个有序的数组;

        (4)通过递归和归并的结合,得出整个数组中的逆序对数量。

623ccf339ef74d5388d687de9e04f9c6.jpg

  • 分解阶段:将数组分解为两个子数组,这个过程需要 O(1) 的时间。
  • 递归计算阶段:递归地计算左子数组和右子数组的逆序对数量,每次递归都将数组大小减半。因为有 log₂(n) 层递归,每层的时间复杂度是 O(n),所以总的时间复杂度是 O(nlogn)。
  • 归并阶段:在归并的过程中,需要线性时间 O(n) 来合并两个有序子数组。因为在每层递归中都会执行这个操作,总的时间复杂度是 O(nlogn)。
  •  综合以上三个阶段,总的时间复杂度是 O(nlogn)。

4. 实现代码 

// 定义递归函数 nxs,用于计算逆序对数量
int nxs(int* nums, int l, int r){
    // 如果子数组的左边界大于或等于右边界,说明子数组中没有元素或只有一个元素,逆序对数量为0
    if(l >= r){
        return 0;
    }

    // 分解:将当前数组划分为两个子数组
    int mid = (l + r) / 2;
    int tl = nxs(nums, l, mid); // 递归计算左子数组中的逆序对数量
    int tr = nxs(nums, mid + 1, r); // 递归计算右子数组中的逆序对数量

    // 求和(采用归并排序的思想)
    int i = l, j = mid + 1, k = 0, count = 0;
    int *B = (int*)malloc(sizeof(int) * (r - l + 1)); // 创建一个临时数组 B 存储归并后的结果

    // 归并过程
    while(i <= mid && j <= r){
        if(nums[i] > nums[j]){
            B[k++] = nums[j++];
            count += (mid - i + 1); // 如果 nums[i] > nums[j],则说明 nums[i] 及其后面的元素都与 nums[j] 构成逆序对
        }
        else{
            B[k++] = nums[i++];
        }
    }
    
    // 处理剩余元素
    while(i <= mid){
        B[k++] = nums[i++];
    }
    while(j <= r){
        B[k++] = nums[j++];
    }

    // 将归并后的结果复制回原数组 nums
    i = l, j = 0;
    while(j < k){
        nums[i++] = B[j++];
    }

    // 返回当前子数组中的逆序对数量
    return tl + count + tr;
}

// 主函数,调用 nxs 函数来计算整个数组中的逆序对数量
int reversePairs(int* nums, int numsSize){
    return nxs(nums, 0, numsSize - 1);
}

 

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/

 

### LeetCode LCR 077 排序链表 #### 题目描述 给定一个未排序的单向链表,返回该链表按升序排列的结果。 #### 解题思路 对于这个问题,可以采用归并排序的思想来解决。具体来说,在处理链表时,可以通过快慢指针找到中间节点,从而将链表分成两部分分别进行排序后再合并这两部分有序链表[^1]。 #### 数据结构与算法分析 此问题主要涉及的数据结构为单向链表。为了有效地对链表进行排序,采用了自底向上或自顶向下两种方式之一来进行归并排序: - **自底向上**:不需要额外空间保存结点位置,通过不断调整步长逐步完成整个列表的排序; - **自顶向下**:利用递归来实现,每次都将当前链表分为大致相等长度的两个子链表直到不能再分为止,之后再依次合并各个已排序的小段形成最终结果[^2]。 下面展示的是基于自顶向下的归并排序的具体代码实现: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def sortList(head: ListNode) -> ListNode: if not head or not head.next: return head # 使用快慢指针寻找链表中点 slow, fast = head, head.next while fast and fast.next: slow = slow.next fast = fast.next.next mid = slow.next slow.next = None # 对前后半部各自排序 left_half_sorted = sortList(head) right_half_sorted = sortList(mid) # 合并已经排好序的部分 dummy_head = tail = ListNode() while left_half_sorted and right_half_sorted: if left_half_sorted.val < right_half_sorted.val: tail.next, left_half_sorted = left_half_sorted, left_half_sorted.next else: tail.next, right_half_sorted = right_half_sorted, right_half_sorted.next tail = tail.next tail.next = left_half_sorted if left_half_sorted is not None else right_half_sorted result = dummy_head.next del dummy_head return result ``` 上述代码实现了完整的链表排序逻辑,其中包含了如何定位链表中心以及怎样高效地执行合并操作等内容[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值