由于我对java很陌生,我正在努力优化程序的时间复杂性。我编写了一个简单的代码,它接受一个数组,并计算有多少对数字,其中数组中索引较低的元素大于索引较大的元素。
例如,如果你有数组:[9,8,12,14,10,54,41],将有4对这样的对:(9,8),(12,10),(14, 10)和(54,41)。
我试图通过不仅将每个元素与每个元素进行比较来优化代码。我的目标是n log n
的时间复杂度。我还没有找到一种以更有效的方式编写此代码的方法。我希望我的问题很明确。
代码(我省略了添加heapsort代码,因为它与我的问题无关。)
import java.util.Scanner;
class Main4 {
static int n;
static int[] A;
// "A" is the input vector.
// The number of elements of A can be accessed using A.length
static int solve(int[] A) {
int counter = 0;
int[] B = new int[n];
B = A.clone();
heapSort(B);
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A.length; j++) {
while( B[j] == Integer.MIN_VALUE&&j+1<n) {
j=j+1;
}
if (A[i] != B[j]) {
counter++;
} else {
B[j] = Integer.MIN_VALUE;
break;
}
}
}
return counter; }
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int ntestcases = scanner.nextInt();
for (int testno = 0; testno < ntestcases; testno++) {
n = scanner.nextInt();
A = new int[n];
for (int i = 0; i < n; i++)
A[i] = scanner.nextInt();
System.out.println(solve(A));
}
scanner.close();
}
}
答案 0 :(得分:0)
您正在寻找所有可能的配对。
您可以从左到右查看所有比赛。这是O(n^2)
解决方案。正如Arkadiy在评论中所建议的那样,这种解决方案适用于输入的最坏情况。
我想到你可能想要按排序顺序存储元素并保留原始的未排序数组。
保留原始数组并构建二叉搜索树。您可以在时间i
中找到包含原始索引O(lgn)
的元素,并在O(lgn)
中将其删除,这很棒。您还可以确定小于第i个元素的值的数量,但需要很少的额外费用。
为了能够计算小于的元素,每个节点必须存储其子项的数量+ 1.当您删除时,只需减少每个节点中的子节点数。插入时,可以增加每个节点中的子节点数。当您搜索节点时,您将值根节点存储在变量和
中一旦停止(找到了节点),就减去右子项的值(如果没有右子,则减去0)并减去该值。
从左到右迭代原始数组。在每一步中,您都可以在树中找到元素,并计算树中较小的元素数量。你知道当前有多少比你当前的要小,你也知道树中的所有元素都有比当前元素更大的索引,这就知道你可以配对多少元素!在计算对数后,从树中删除此元素。你做了n次。查找和从树中删除O(lgn)
== O(nlgn)
时间复杂度!总时间为O(nlgn + nlgn) = O(nlgn)
!!
算法简介(第3版)第12章深入介绍了如何实施BST。您可能还会在互联网上找到许多用图片解释它的资源。
答案 1 :(得分:0)
将整个列表W
分成两部分L
和R
早期相等的部分。 W
的计数是
L
和R
(l, r)
与l > r
和l
分别属于r
和L
的{{1}}对的对数。第一个项目是递归。第二个项目符号不依赖于列表R
和L
的排序。因此,您可以使用单个传递两个列表对它们进行排序并确定结果(对排序R
的第一个元素计算排序r
中的所有较小R
,计算第二个元素的计数现在逐步计算,等等。)
时间复杂度由
给出L
我猜是 T(n) = T(n/2) + T(n/2) + O(n log n)
。无论如何,它比O(n log n)
小得多。
您可以通过使用合并排序来改进它:您需要排序O(n*n)
,这可以通过合并已排序的L
和已排序的LL
(这是{的两个部分}来获得{1}}在递归步骤中。)
选择一个元素LR
,使得较大和较小元素的数量大致相同(中位数将是完美的,但也可以使用随机选择的元素)。
单次通过数组并计算小于L
的元素数量。再做第二遍并计算m
对m
,(x, y)
和x
以及y
左侧。
将列表拆分为两部分:元素x >= m
和其余部分。冲洗并重复。