【问题标题】:Is there a faster way to compare two Int arrays in Java?有没有更快的方法来比较 Java 中的两个 Int 数组?
【发布时间】:2014-07-22 09:07:13
【问题描述】:

我有两个整数数组,每个 大小相同,比如 n(n 是可变的,所以我可以有两个大小为 4 或 5 或 6 等的数组)以及每个数字的值范围可以取的范围是0-9。 示例

Integer[] one = {1,9,3,4} 
Integer[] two = {1,1,9,3}

现在,我想比较数组一和二,这样 1) 我可以获得相同且位于相同位置的元素的数量。 2)我可以得到相同但不在同一位置的数字。

我采取的方法是

对于 (1) 遍历数组 1 并为每个索引检查 one[i] == two[i]。 - 简单。

对于 (2) 遍历两个数组,对于 i != j,查看元素是否相同,如果相同,用 -1 标记它们以避免将来发生冲突。

for(int i =0;i<one.length;i++){
    for(int j=0;j<two.length;j++){
        if(i != j && one[i] != -1 && two[j] !=-1)){
            if(one[i] == two[j]){
                whiteCount++
                one[i] = -1;
                two[j] = -1;
            }
        }
    }
}

问题:现在我想知道是否有更快的方法来做同样的事情?特别是。计算问题的(2)nd 部分。 这是获得Mastermind棋盘游戏黑白钉计算的基本比较方法。 谢谢 沙克蒂

更新 1: 1) Rudi 的建议将 Integer[] 改为 int[]

2) 使用 Dave Challis 的解决方案 性能变化 对于 7776 X 7776 计算

OLD 46950 ms
NEW 42887 ms

【问题讨论】:

  • @lpratlong OP 也要求在同一位置获取数字。
  • @Ipratlong - 我不这么认为
  • 你在Levenshtein Distance之后吗?
  • 多个匹配项呢?你希望如何处理这些。例如Integer[] one = {1,9,2,1};Integer[] two = {6,1,7,4};。您希望这里有多少场比赛? 1 或 2 用于您的 2) 案例?
  • 顺便说一句,我还建议使用 visualvm 或类似工具来分析您的代码,并找出大部分时间实际花费在哪里,它应该会给您一些关于要花费哪些代码的提示优化时间。

标签: java arrays performance


【解决方案1】:

虽然这可能不是您想要的,但我们可以通过一个非常简单的更改来显着减少操作数量。

来自

Integer[] one = {1,9,3,4} 
Integer[] two = {1,1,9,3}

int[] one = {1,9,3,4} 
int[] two = {1,1,9,3}

这会稍微加快处理速度,但不会优化排序/搜索逻辑本身。我们所做的只是删除自动装箱和自动拆箱操作。但是,如果您在非常大的范围内这样做,那么这可能会产生重大影响。

【讨论】:

    【解决方案2】:

    下面的解决方案是 O(2N),不使用任何额外的库,也不修改初始数组。

    它遍历两个数组一次以获取相同位置的整数计数。在执行此操作时,它会建立第二个数组中每个数字的计数(并存储在counts 数组中)。

    然后它再次遍历第一个数组,得到每个数字在第二个数组中的总次数:

    final Integer[] one = {1,9,3,4};
    final Integer[] two = {1,1,9,3};
    
    int samePositionCount = 0;
    int sameNumberCount = 0;
    
    // tracks number of times an int is in the 2nd array
    final Integer[] counts = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    for (int i = 0; i < one.length; i++) {
        if (one[i].equals(two[i])) {
            samePositionCount++;
            counts[one[i]] = -1; // mark as seen in same position count
        } else if (counts[two[i]] != -1) {
            counts[two[i]]++;
        }
    }
    
    for (int i : one) {
        if (counts[i] > 0) {
            sameNumberCount += counts[i];
            counts[i] = 0; // avoid adding twice
        }
    }
    
    System.out.println(samePositionCount + " " + sameNumberCount);
    

    打印:

    1 2
    

    【讨论】:

    • 原帖说每个整数可以取0-9的范围,所以我这里使用了一个固定大小的数组。如果不是这样,我会换成使用某种 Map
    • @DaveChallis - 答案应该是 1,2 。第一个索引 1 在数字和 9,3 中都存在但在不同的位置匹配
    • @Shakti 很容易解决这个问题
    • @Shakti 啊,抱歉,如果第二部分已经在第一部分,则错过了关于不计算比赛的部分。考虑到这一点,我会修正答案。
    • @Shakti 现已修复,如果某个位置的值匹配,则将值 -1 存储在 counts 中。
    【解决方案3】:

    要获得相同但在不同位置的数字的数量,您可以这样做。

    public static long[] encode(int... nums) {
        long[] ret = new long[nums.length];
        for (int i = 0; i < nums.length; i++) {
            ret[i] = ((long) nums << 32) + i;
        }
        Arrays.sort(ret);
    }
    
    // encode both arrays and do a merge sort, skipping matches which have the same index.
    

    这是一个 O(n log N) 操作。


    您可以将one[i] != -1 移出,以便它可以跳过该值。

    int[] one = {1,9,3,4}; // Using int is faster and clearer.
    int[] two = {1,1,9,3};
    
    for (int i = 0; i < one.length; i++){
        if (one[i] == -1) continue;
        for (int j = 0; j < two.length; j++){
            if (one[i] == two[j] && i != j && two[j] != -1) {
                whiteCount++
                one[i] = -1;
                two[j] = -1;
            }
        }
    }
    

    首先放置one[i] == two[j] 可以提高性能,因为它通常是错误的,因此不需要检查其他内容。

    【讨论】:

    • +1 用于继续减少运营的战略用途。
    • 只需将guessStatus 重命名为1,将secretStatus 重命名为2。我这边的复制粘贴不正确。
    • @Shakti 改变了问题。我们可以放弃i != j,因为那你有一个 O(N log N) 的问题吗?
    • 其实 i != j 是我要微调这个方法的部分
    • @Shakti 你仍然可以这样做,但它有点复杂。您可以进行合并排序,检查原始索引。
    【解决方案4】:

    为什么不使用现有的实用方法来比较 aaarays。他们肯定更快。您可以检查“等于”方法的实现并确认。

    import java.util.Arrays;
    
    class Test {
    public static void main(String[] args) {
        int inarr1[] = {1, 2, 3};
        int inarr2[] = {1, 2, 3};
        Object[] arr1 = {inarr1};
        Object[] arr2 = {inarr2};
        if (Arrays.deepEquals(arr1, arr2))
            System.out.println("Same");
        else
            System.out.println("Not same");
       }
    

    }

    【讨论】:

    • 这并没有完成大部分原始代码的工作。
    • 我想他想比较数组的每个值。
    猜你喜欢
    • 2020-02-26
    • 2023-04-10
    • 1970-01-01
    • 2021-04-17
    • 2017-05-03
    • 2021-09-13
    • 1970-01-01
    • 2014-05-15
    • 2015-07-04
    相关资源
    最近更新 更多