实现归并排序代码时不能计算所有的倒置
Can't count all the inversions while implementing mergesort code
我一直在试图弄清楚如何让这段代码计算所有的倒置,但我似乎无法理解。根据我的理解,这段代码应该计算所有的反转,但它在许多测试用例中失败,在正确的方向上轻推,甚至整个修复都会受到赞赏。
代码:
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
块进行一些更改或者我添加反转的方式会修复它,它只是必须,这就是重点mergesort,这就是为什么我坚持以这种方式解决它,而不是仅仅使用其他代码。问题是;我正在做 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;
}
我一直在试图弄清楚如何让这段代码计算所有的倒置,但我似乎无法理解。根据我的理解,这段代码应该计算所有的反转,但它在许多测试用例中失败,在正确的方向上轻推,甚至整个修复都会受到赞赏。
代码:
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
块进行一些更改或者我添加反转的方式会修复它,它只是必须,这就是重点mergesort,这就是为什么我坚持以这种方式解决它,而不是仅仅使用其他代码。问题是;我正在做 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;
}