You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++归并排序统计逆序对时合并函数清空数组的原因及替代方案

归并排序统计数组逆序对实现说明

核心思路

使用归并排序统计逆序对的核心逻辑分为两部分:

  • 递归拆分原数组,分别统计左、右子数组内部的逆序对数量
  • 合并两个已排序的子数组时,统计跨左右子数组的逆序对数量
    两部分相加即为当前数组的总逆序对数量。

原实现代码

int count_and_merge(vector<int>& array, const vector<int>& left_subarray, const vector<int>& right_subarray) {
    vector<int> merged {};
    array.clear();
    int left_index = 0, right_index = 0, sorted_index = 0;
    int inversions = 0;
    while(left_index < left_subarray.size() and right_index < right_subarray.size()) {
        if(left_subarray[left_index] <= right_subarray[right_index])
            array.push_back(left_subarray[left_index++]);
        else {
            array.push_back(right_subarray[right_index++]);
            inversions += left_subarray.size() - left_index;
        }
    }
    while(left_index < left_subarray.size()) array.push_back(left_subarray[left_index++]);
    while(right_index < right_subarray.size()) array.push_back(right_subarray[right_index++]);
    return inversions;
}

int count_inversions_and_sort(vector<int>& array) {
    if(array.size() <= 1) return 0;
    int n = array.size();
    vector<int> left_subarray(array.begin(), array.begin() + n / 2),
                right_subarray(array.begin() + n / 2, array.end());
    
    int left_subarray_inversions  = count_inversions_and_sort(left_subarray),
        right_subarray_inversions = count_inversions_and_sort(right_subarray);
    return left_subarray_inversions + right_subarray_inversions + count_and_merge(array, left_subarray, right_subarray); 
}

疑问解答

1. 为什么必须先执行array.clear()?

你当前的实现用push_back方法向array中添加元素,该方法会在数组的末尾追加新元素。如果不清空数组,array中还保留着拆分前的旧数据,合并后的新元素会追加在旧数据之后,最终得到的数组长度会是预期的2倍,内容也会包含错误的旧数据,导致上层递归逻辑出错。
你平时常用的array[sorted_index++] = xxx写法是直接覆盖数组对应位置的旧元素,不需要追加操作,自然不需要提前清空。

2. 无需清空数组的实现方式

存在无需清空的实现,就是采用你熟悉的下标赋值写法即可。进入count_and_merge时,array的长度刚好等于左右子数组的长度之和,足够容纳合并后的结果,直接覆盖原有位置的内容即可,示例代码如下:

int count_and_merge(vector<int>& array, const vector<int>& left_subarray, const vector<int>& right_subarray) {
    int left_index = 0, right_index = 0, sorted_index = 0;
    int inversions = 0;
    while(left_index < left_subarray.size() && right_index < right_subarray.size()) {
        if(left_subarray[left_index] <= right_subarray[right_index])
            array[sorted_index++] = left_subarray[left_index++];
        else {
            array[sorted_index++] = right_subarray[right_index++];
            inversions += left_subarray.size() - left_index;
        }
    }
    while(left_index < left_subarray.size()) array[sorted_index++] = left_subarray[left_index++];
    while(right_index < right_subarray.size()) array[sorted_index++] = right_subarray[right_index++];
    return inversions;
}

该版本完全去掉了clear操作和push_back调用,和常规归并排序的实现逻辑一致。

内容的提问来源于stack exchange,提问作者Mutating Algorithm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 17:12:01