【问题标题】:Array algorithm performance kata数组算法性能kata
【发布时间】:2022-01-18 19:01:25
【问题描述】:

试图用这个来夸大算法开发:


You are given an array of integers a and an integer k. Your task is to calculate the number of ways to pick two different indices i < j, such that a[i] + a[j] is divisible by k.

Example

For a = [1, 2, 3, 4, 5] and k = 3, the output should be solution(a, k) = 4.

这是我的 java 解决方案:

long solution(int[] a, int k) {
    
    final BiPredicate<Integer, Integer> isDivisible = (x,y) -> (a[x] + a[y]) % k == 0;
    long counter = 0;
    for(int i = 0; i < a.length - 1; i++) {
        for(int j = i + 1; j < a.length; j++ ){
            if(isDivisible.test(i,j)) {
               counter++; 
            }
        }
    }
    return counter;
}

它通过了所有性能测试,必须有一些更高性能的解决方案,有什么想法吗?

【问题讨论】:

  • 你能链接到codewars kata吗?
  • 问题链接在哪里?

标签: java algorithm


【解决方案1】:

您的方法是一种蛮力解决方案,并且具有二次时间复杂度。

这是一个改进:

考虑两个数之和是k的倍数,当任一时

  • 它们都是k的倍数,或者
  • 余数除以k后的总和为k

如果我们可以计算每个可能的余数有多少个数,我们可以找出 补数余数有多少个,然后取乘积。最后,我们需要将这个总数减半,因为我们还计算了i &gt; j 的情况。余数为 0 或为 k 的一半的情况需要特别注意,因为该产品会包含 i == j 的情况,因此需要丢弃这些情况。

这是一个实现:

long solution(int[] a, int k) {
    final HashMap<Integer, Integer> count = new HashMap<>();
    for (int i = 0; i < a.length; i++) {
        int key = a[i] % k;
        count.put(key, count.getOrDefault(key, 0) + 1);
    }
    int counter = 0;
    for (Map.Entry<Integer, Integer> set : count.entrySet()) {
        int mod = set.getKey();
        int freq = set.getValue();
        counter += freq * (mod > 0 && k != 2*mod 
                          ? count.getOrDefault(k - mod, 0) 
                          : freq - 1);
    }
    return counter / 2;
}

【讨论】:

    猜你喜欢
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    相关资源
    最近更新 更多