基本上我正在尝试用Java编写一个算法来确定数组中乱序的对数。因此,如果我们取i和j并且j在阵列中的位置比i高,但是A [i]> A [j]然后它将这两个数字计为反转。目前这就是我所拥有的:
for(int i = 0; i<n-1; i++){
if (A[i] > A[i+1]){
k++;
这样做只是比较了彼此旁边的对,所以现在我试图修改它以找到数组中的任何两个数字,其中较低位置的值高于较高位置的数字。我知道如何做这样的事情,但我希望运行时间为(n + k),其中n是数组的长度,k是数组中的反转次数。
编辑:这是我尝试实现插入排序:
int k = 0;
int [] A = {5, 4, 3, 2, 1};
int n = A.length;
for(int i = 1; i < n; i++){
int temp = A[i];
int j;
for (j = i - 1; j >=0 && temp < A[j]; j--){
A[j + 1] = A[j];
A[j + 1] = A[j];
k++;
k应该跟踪多少次反转。对于数组5,4,3,2,1,我返回的数字是6.是吗?
答案 0 :(得分:2)
解决方案是实现插入排序,并计算交换一对相邻元素的次数。这是有效的,因为插入排序只为每次反转执行交换。事实上,它的运行时间是 O ( n + k ),正如您所要求的那样。
至于问题第二部分 - 这是更正后的插入排序算法:
for (int i = 1; i < n; i++) {
int temp = A[i];
int j;
for (j = i - 1; j >= 0 && temp < A[j]; j--) {
A[j + 1] = A[j];
k++; // Number of inversions
}
A[j + 1] = temp;
}
额外注意:计算数组反转的有效方法是修改合并排序算法,该算法在 O ( n log n >中运行) 时间。但是,当 k 很小时, O ( n + k )大约 O ( n ),小于 O ( n log n )。实际上,合并排序的最佳时间仍然是 O ( n log n ),而插入排序最好case是 O ( n )。因此,合并排序不会回答OP对 O ( n + k )的问题算法
答案 1 :(得分:0)
数组的反转计数表示 - 数组的排序距离(或接近)。如果数组已经排序,则反转计数为0.如果数组按相反顺序排序,则反转计数最大。 从形式上讲,如果a [i]> 1,则[i]和[j]两个元素形成反转。 a [j]和i&lt; j示例: 序列2,4,1,3,5有三个反转(2,1),(4,1),(4,3)。
对于每个元素,计算在其右侧并且小于它的元素数量。
int getInvCount(int arr[], int n)
{
int inv_count = 0;
int i, j;
for(i = 0; i < n - 1; i++)
for(j = i+1; j < n; j++)
if(arr[i] > arr[j])
inv_count++;
return inv_count;
}
/* Driver progra to test above functions */
int main(int argv, char** args)
{
int arr[] = {1, 20, 6, 4, 5};
printf(" Number of inversions are %d \n", getInvCount(arr, 5));
getchar();
return 0;
}