目标是找到整数数组中的反转次数。例如,
给出:(1,3,5,2,4,6)
反转是:(3,2),(5,4),(5,2)。
也就是说,共有三个反转。 O(n ^ 2)解决方案需要两个for循环,但对于大型输入数组需要太长时间。由于合并排序需要O(n(log(n)))时间,因此在这种情况下实现它是有意义的。
通过划分&征服方法,我们可以实现O(n(log(n)))。解决方案是所采取的倒置的总和。反转如下(对于大小为'n'的输入数组):
如果i,j <= n / 2 ,则左反转 如果i,j&gt;
正确反转n / 2
如果i <= n / 2,则分裂反转。 Ĵ
注意:当arr [i]&gt;时,完成分割反转。 arr [j]和i&lt;学家
在上述权利要求的基础上,这是我写的下面的算法(其中我首先编写了合并排序,然后相应地调整它以返回反转次数),我得到了错误的输出。我无法弄清楚我哪里出错了。
(如果需要,请询问其他信息。我已经坚持了一段时间)。
#include<iostream>
#include<vector>
using namespace std;
int merge(vector <int> & arr, int l, int m , int r)
{
int i,j,k;
int count = 0;
int n1, n2;
n1=m-l+1;
n2=r-m;
//temporary arrays to store the elements.
int L[n1];
int R[n2];
for (int i = 0; i < n1; ++i)
{
L[i]=arr[l+i];
}
for (int j = 0; j < n2; ++j)
{
R[j]=arr[m+1+j];
}
i=0;
j=0;
k=l;
while(i<n1 && j<n2)
{
if (L[i]<R[j])
{
arr[k]=L[i];
i++;
}
else
{
arr[k]=R[j];
j++;
count=count+(m-i);
}
k++;
}
while(i<n1)
{
arr[k]=L[i];
i++;
k++;
}
while(j<n2)
{
arr[k]=R[j];
j++;
k++;
}
return count;
}
int mergeSort(vector <int> & arr, int l, int r)
{
int m;
int count=0;
/*
if (l<r)
{
m=l+(r-l)/2;
mergeSort(arr, l, m);//used to recursively sort the left half of the array
mergeSort(arr,m+1,r);//used to recursively sort the right half of the array
merge(arr,l,m,r);//merges both arrays together.
}
*/
if(l<r)
{
m = (l + r) / 2;
count =
(mergeSort(arr, l, m) +
mergeSort(arr, m+1, r) +
merge(arr, l, m, r));
return count;
}
else
return 0;
}
void printArray(vector <int> A, int size)
{
for (int i = 0; i < size; ++i)
{
cout<<A[i]<< " ";
}
cout<<endl;
}
int main()
{
int n;
cin>>n;
//int arr[n];
vector<int> arr(n);
int i;
for (i=0; i<n; i++) {
cin>>arr[i];
}
/*
cout<<"the given array is : "<<endl;
printArray(arr, n);
*/
cout<<"the number of inversions are : "<<endl;
cout<< mergeSort(arr, 0, n - 1) <<endl;
/*
cout<<"the sorted array is : "<<endl;
printArray(arr, n);
*/
return 0;
}
测试用例:
案例1
输入:
(对于n = 6)
1 3 5 2 4 6
预期产出: 3
获得输出: 1
案例2
输入:
(对于n = 15)
9 12 3 1 6 8 2 5 14 13 11 7 10 4 0
预期产出: 56
获得输出: 125
答案 0 :(得分:2)
问题在于计算我们在每一步中获得的反转次数。让我们来看看合并: 我们有两个数组L和R,并且在每次迭代中我们查看每个数组中的第一个数字(因为它们已经被排序):
1)。 L [i]&lt; = R [j]。这意味着L [i]不会使用来自R的一些剩余元素创建新的反转。
2)。 L [i]&gt; [R [J]。这意味着R [j]将产生L [i],L [i + 1],L [i + 2],...,L [n1 - 1]的反演。从我看到你的错误是计数计算。您添加(m - i)而不是(n1 - i)。 我看到的另一个错误是计数类型。如果你假设尺寸相当大(~10 ^ 5),你需要一些更大的类型来存储你的价值。
希望这有帮助。