c++ - 实现合并排序代码时无法计算所有反转

标签 c++ algorithm sorting mergesort

我一直在试图弄清楚如何让这段代码来计算所有反转,但似乎无法具体说明。据我了解,这段代码应该计算所有的反转,但它失败了许多测试用例,在正确的方向上轻推,甚至整个修复将受到赞赏。

代码:

int countInversion(vector<int>& v, int& inv) {
    if(v.size() > 1) {
        vector<int> left(v.begin(), v.begin() + v.size()/2);
        vector<int> right(v.begin() + v.size()/2, v.end());

        countInversion(left, inv);
        countInversion(right, inv);

        int l = 0; int r = 0;

        for(int i = 0; i < v.size(); i++) {
            if(r >= right.size() || (l < left.size() && left[l] < right[r])) {
                v[i] = left[l++];
            } else {
                if(right[r] < left[l]) inv += left.size() - l;
                v[i] = right[r++];  
            } 
        }
    } return inv;
}

确实有效的代码(我在互联网上找到的)具有非常低的 可读性有人可以帮助我理解它吗?更重要的是,请指出我的代码到底遗漏了什么,以及是否可以纠正我的代码以正确计数?谢谢!

代码2:

long long ans = 0;

void mergei(int a[],int i,int j) {
    int ni = ((i+j)/2) + 1, nj = j + 1;
    int s = i;
    int* arr = new int [j - i + 1];
    j = ni;
    int k = 0;

    while(i < ni && j < nj) {
        if(a[i] <= a[j]) {
            arr[k] = a[i++];
        } else {
            arr[k] = a[j++];
            ans += (ni - i);
        } k++;
    }

    for(; i < ni; i++, k++) arr[k] = a[i];
    for(; j < nj; j++, k++) arr[k] = a[j];
    for(k = 0; s < nj; s++, k++) a[s] = arr[k];
    delete [] arr;
}

void m_sort(int a[],int i,int j) {
    if(i < j) {
        m_sort(a, i, (i+j)/2);
        m_sort(a, ((i+j)/2) + 1, j);
        mergei(a, i, j);
    }
}

最佳答案

我终于找到了一种使用我的代码来解决它的方法,我确信对 if else 进行了一些更改 block 或者我如何添加反转会修复它,它只是必须,这就是合并排序的全部要点,这就是为什么我坚持以这种方式解决它,而不是仅仅使用另一个代码。问题是;我在做left[l] < right[r]如果它是向左或向右合并,这并不重要,但对于反转却很重要,只需将其更改为 left[l] <= right[r] .

long countInversions(vector<int>& arr, long& inv) {
    if(arr.size() > 1) {
        vector<int> left(arr.begin(), arr.begin() + arr.size()/2);
        vector<int> right(arr.begin() + arr.size()/2, arr.end());

        countInversions(left, inv);
        countInversions(right, inv);

        int l = 0; int r = 0;

        for(int i = 0; i < arr.size(); i++) {
            if(r >= right.size() || (l < left.size() && left[l] <= right[r])) {
                arr[i] = left[l++];
                // inv += r;
            } else {
                arr[i] = right[r++];
                inv += left.size() - l;
            }
        }
    } return inv;
}

稍微好一点、更易读的代码是:

long countInversions(vector<int>& v) {
    if(v.size() <= 1) return 0;

    vector<int> left(v.begin(), v.begin() + v.size()/2);
    vector<int> right(v.begin() + v.size()/2, v.end());

    long inv = countInversions(left) + countInversions(right);

    int l = 0, r = 0;

    for(int i = 0; i < v.size(); i++) {
        if(r >= right.size() || (l < left.size() && left[l] <= right[r])) {
            v[i] = left[l++];
            // inv += r;
        } else {
            v[i] = right[r++];
            inv += left.size() - l;
        }
    }     
    return inv;
}

关于c++ - 实现合并排序代码时无法计算所有反转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59475543/

相关文章:

c++ - 如何绘制所有面都具有不同纹理的立方体?

c++ - 分段初筛

python - 试图创建一个解决迷宫的程序,但它卡在了特定的路径上

python - 如何根据另一个列表对一个列表进行排序?

c++ - fseek 写入值时回到文件末尾

c++ - 向后返回的 C++ 递归

Python同步读取排序文件

javascript - 为什么这种方式不起作用

c++ - 从对 <first,last> 分配 vector

c - 插入排序汇编代码(C译)