优化程序的时间复杂度,计算不同数字对的数量,如下所述

时间:2017-11-06 20:58:34

标签: java optimization time-complexity

由于我对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();
    }
}

2 个答案:

答案 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)

划分并征服1(合并排序)

将整个列表W分成两部分LR早期相等的部分。 W的计数是

的总和
  • 计算LR
  • (l, r)l > rl分别属于rL的{​​{1}}对的对数。

第一个项目是递归。第二个项目符号不依赖于列表RL的排序。因此,您可以使用单个传递两个列表对它们进行排序并确定结果(对排序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}}在递归步骤中。)

分而治之2(快速排序)

选择一个元素LR,使得较大和较小元素的数量大致相同(中位数将是完美的,但也可以使用随机选择的元素)。

单次通过数组并计算小于L的元素数量。再做第二遍并计算mm(x, y)x以及y左侧。

将列表拆分为两部分:元素x >= m和其余部分。冲洗并重复。