唯一标识一系列数字,其顺序并不重要

时间:2016-12-17 20:56:57

标签: java arrays processing-efficiency

我们说我有这3个整数数组:

int[] a = {1, 2, 3};
int[] b = {3, 4, 5};
int[] c = (2, 1, 3};

我正在寻找与c相同的最有效代码(因为它们包含相同的数字,但顺序不同),但考虑与b不同,b与c不同。 / p>

我知道我可以对它们进行排序,以便c变为{1,2,3},因此与a相同,但是我比较了数百个阵列,每个阵列超过三个,我不知道'我希望我的程序能够对每一个程序进行排序,我认为必须有更好的方法。

另外,例如,取总和不会起作用,因为{1,4,5}中的数字总和与{1,3,6}中数字的总和相同。

产品无法正常工作,因为{1,2,6}中的数字乘积与{1,3,4}中的数字相同。

3 个答案:

答案 0 :(得分:2)

排序是一个O(nlog(n)操作(在最坏的情况下)。相反,您可以通过遍历两个数组并只计算其中的元素来获得O(n)解决方案:

public static boolean hasSameElements(int[] a, int[] b) {
    return countElements(a).equals(countElements(b);)
}

private static Map<Integer, Long> countElements(int[] arr) {
    return Arrays.stream(arr)
                 .boxed()
                 .collect(Collectors.groupingBy(Function.identity(), 
                          Collectors.counting()));
}

编辑:
虽然它不会改变算法的大O符号,但是一个稍微不太优雅的解决方案可以通过快速失败对非匹配阵列执行得更好:

public static boolean hasSameElements(int[] a, int[] b) {
    if (a.length != b.length) {
        return false;
    }

    Map<Integer, Long> popCount =
            Arrays.stream(a)
                  .mapToObj(Integer::valueOf)
                  .collect(Collectors.groupingBy(Function.identity(), 
                           Collectors.counting()));

    for (int elem : b) {
        Long count = popCount.get(elem);
        if (count == null) {
            return false;
        }
        count--;
        if (count == 0L) {
            popCount.remove(elem);
        } else {
            popCount.put(elem, count);
        }
    }

    return popCount.isEmpty();
}

答案 1 :(得分:2)

我假设数组没有任何内部重复项,如{1,2,2,4}。首先检查长度是否相同。如果长度相同,则从第一个数组创建Set。将第二个数组A2中的元素一次添加到集合中。当添加A2中的每个元素时,检查它是否已添加,并且不作为重复项被拒绝。如果来自A2的任何元素不是重复的,则两个数组不相同。如果A2中的所有元素都作为重复项被拒绝,那么这两个数组的大小和内容相同,但不一定按顺序排列。

答案 2 :(得分:-1)

将数组中的所有数字减少为单个数字进行比较的想法是在正确的轨道上。这种方法称为散列。散列的一个好特性是尽可能避免将多组输入映射到同一输出。加法和乘法是非常差的散列函数,并且有关于良好散列函数的大量文献。在java中,您可以使用Arrays.hashCode(int [])函数来获得数组的良好散列。

当然,尽管这种散列具有良好的质量,但不能保证两个阵列不会产生相同的值。那么,以下是如何实现比较函数:

y = lambda x : x**2
dy_dx = lambda x : 2*x
def gradient_descent(function,derivative,initial_guess):
    optimum = initial_guess
    while abs(derivative(optimum)) > 0.01:
        optimum = optimum - 0.01*derivative(optimum)
        print((optimum,derivative(optimum)))
    else:
        return optimum

请注意,仅当两个参数未指向同一个数组并且散列相同时,才会执行逐个元素的比较。

编辑: 有人向我指出,boolean equals(int[] a, int[]b) { if (a.length != b.length) return false; if (a == b) return true; if (Arrays.hashCode(a) != Arrays.hashCode(b)) return false; for(int i=0; i< a.length; i++) { if (a[i] != b[i]) return false; return true; } 可能会为不同顺序中具有相同值的数组产生不同的结果,这是真的,事实上我忽略了排序。在平均情况下,首先对数组进行排序是O(M NlogN)(M是数组的数,N是平均长度)。但是,如果数组中的重复次数很少,则avg复杂度更接近于O(M N),因为只需要对具有相同长度和哈希码的数组进行排序,这是非常不可能的。

Arrays.hashCode