反转计数算法无需使用合并排序(C )
Inversion Count Algorithm without using Merge Sort (c++)
我一直在努力几天,以提出以下伪代码以计算未分类置换数字列表的倒置数量的代码。我需要在O(nlogn(时间运行的算法,但我只能想到O(n^2logn(时间的解决方案。
更具体地说,我想知道如何通过不使用嵌套循环来加快第二步。我知道还有其他有效的算法(即合并选项(可以起作用,但我需要遵循psoudo代码的步骤。
Instance: An array A[1] . . . A[n], a permutation of n numbers 1, . . . , n
Question: Calculate vector B[j] = |{A[i] : j > i and A[i] > A[j]}| (the same as
B[j] = |{i : j > i and A[i] > A[j]}|) B[j] is the number of element
larger than A[j] to the left of A[j] in t the array A. In other words,
the sum of the elements in B is equal to the number of inversions in
the permutation A[1] . . . A[n].
(1) Initialize B[i] to 0.
(2) For each even A[j] find elements with indices smaller than j that are by one larger
than A[j]: increase B[j] by the number of such elements;
(3) Divide each A[i] by 2 (in the integer sense);
(4) Stop when all A[i] are 0.
以下是我到目前为止提出的代码:
long long numInversions = 0;
// number of elements that are zero in the array
unsigned int zeros = 0;
do {
// solution will need to replace this nested
// for loop so it is O(n) not O(n^2)
for (int i = 0; i < permNumber; i++){
// checks if element is even
if(array[i] % 2 == 0){
for (int j = i; j >= 0; j--){
if (array[j] == array[i] + 1){
numInversions++;
}
}
}
}
// resets value of zeros for each pass
zeros = 0;
for (int k = 0; k < permNumber; k++){
array[k] = array[k] / 2;
if (array[k] == 0)
zeros++;
}
} while(zeros != permNumber);
注意:该算法应返回列表中的反转数,标量。伪代码要求一个数组,但最终将数组的元素求和以计算反转计数。
Example: Consider a permutation (2, 3, 6, 1, 3, 5) with six inversions. The
above algorithm works as follows:
2 4 6 1 3 5 (no pairs) ÷2
1 2 3 0 1 2 1 = 0: one '1' to left, 2: one 3 to left ÷2
0 1 1 0 0 1 1 = 0: two '1's to left, 0: two '1's to left ÷2
0 0 0 0 0 0 total: 6 pairs
这是一种非常聪明的算法 - 在每种迭代中,它都会计算两分师将删除的反转...尽管不需要为B
使用数组,因为您可以将其添加到元素中,然后将它们总结。您只能保留一个运行总和。
无论如何...为了加快步骤(2(,您可以使用另一个数组C[v]
来记住A
中所有奇数的计数,例如:
Step 2:
Initialize all C[v] to 0
For i = 1 to n: //0 to n-1 if you're using 0-based arrays
if A[i] is even then:
B[i] += C[A[i]+1]
else:
C[A[i]] += 1
不使用Merge Sort,在Java中:
public int binarySearch(ArrayList<Integer> A, int s, int e, int elem){
// finds the position at which elem can be inserted to maintain the sorted order in A
if (s >= e){
return elem >= A.get(s) ? s+1 : s;
}
int mid = (s+e)/2;
if (elem == A.get(mid)) return mid+1;
if (elem < A.get(mid)) return binarySearch(A, s, mid-1, elem);
return binarySearch(A, mid+1, e, elem);
}
public int binarySearchLast(ArrayList<Integer> A, int s, int e, int elem){
// finds the index of first element greater than "elem" in list A
if (s >= e) return elem < A.get(s) ? s : s+1;
int mid = (s+e)/2;
if (elem < A.get(mid)) return binarySearchLast(A, s, mid, elem);
return binarySearchLast(A, mid+1, e, elem);
}
public int countInversions(ArrayList<Integer> A) {
int cnt = 0;
ArrayList<Integer> B = new ArrayList<>();
B.add(A.get(0));
for (int i = 1; i < A.size(); i++){
int idx = binarySearch(B, 0, B.size()-1, A.get(i));
B.add(idx, A.get(i));
idx = binarySearchLast(B, 0, B.size()-1, A.get(i));
cnt = cnt + B.size() - idx;
}
return cnt;
}
相关文章:
- 使用C++程序合并排序没有得到正确的输出
- 用于合并排序的合并函数
- 合并排序不排序自创建数组类 c++
- 仅在大型阵列上出现合并排序分段错误
- C++合并排序可视化工具
- 没有输出的合并排序我做错了什么?
- 字符串上的合并排序上的 Seg 错误
- 使用向量在 c++ 中合并排序实现
- 我无法让我的合并排序实现运行
- 合并排序:分段错误核心转储
- 合并排序中的错误计数:计数反转
- C++ 多线程 - 与线程合并排序的算法替代
- C++中合并排序算法的奇怪行为
- 合并排序没有给我任何输出
- C++ 中的合并排序
- 数组为此合并排序函数提供了正确的输出,但向量给出了不正确的输出.出了什么问题?
- 在实现合并排序代码时无法计算所有反转
- 在C++中使用迭代器合并排序
- 运行合并排序递归算法时EXC_BAD_ACCESS错误
- 我的C++合并排序代码不起作用。我在这里错过了什么?