【问题标题】:Codility - Counting Elements Lessons : fastest algorithm swapCodility - 计数元素课程:最快的算法交换
【发布时间】:2014-11-15 11:07:31
【问题描述】:

我是studying Codility chapter 2 : Counting elements

我试着做这个练习,我认为我有一个很好的解决方案 O(n)。这是一个有效的解决方案吗? 是不是比课上提出的 BEST 方案更好?

问题:给定一个整数 m (1 ???? m ???? 1 000 000) 和两个非空、零索引的数组 A 和 B,其中包含 n 个整数, a0,a1,...,an−1 和 b0,b1,...,bn−1 分别为 (0 ???? ai,bi ???? m)。目的是检查是否存在可以对这些数组执行的交换操作,使得数组 A 中的元素之和等于交换后数组 B 中的元素之和。通过交换操作,我们的意思是从数组 A 中选择一个元素,然后 数组 B 中的一个元素并交换它们。

我用这些值测试了我的解决方案: int a[] = {2, 7, 12, 16}; int b[] = {4, 8, 9}; m = 16;

注意:我评论了 return 以查看交换的值。

 public int resultat(int[] A, int B[], int max) {

    int sumA = Arrays.stream(A).sum();
    int sumB = Arrays.stream(B).sum();

    int[] countA = count(A, max);
    int[] countB = count(B, max);
    int diff = sumA - sumB;
    int diffMin = 0;

    if (diff % 2 != 0) {
        return -1;
    }
    diffMin = diff / 2;
    if (sumA > sumB) {

        if (diff < countA.length && diffMin < countB.length && countA[diff] != 0 && countB[diffMin] != 0) {
            System.out.println("A:" + diff + "- B:" + diffMin);
            //return 1;
        }
    } else {

        if (diffMin < countA.length && diff < countB.length && countB[diff] != 0 && countA[diffMin] != 0) {
            System.out.println("A:" + diffMin + "- B:" + diff);
            //return 1;
        }
    }
    return -1;

}

public int[] count(int[] X, int max) {
    int[] p = new int[max + 1];
    Arrays.fill(p, 0);
    for (int i = 0; i < X.length; i++) {
        p[X[i]] += 1;
    }
    return p;
}

【问题讨论】:

  • 我用这些值测试了我的解决方案。你是怎么测试的,有没有使用java程序员经常使用的测试框架?
  • 我没有为这种情况使用任何测试框架 java。我用我想要的值创建了一个类。我知道 Junit,我将尝试使用它。你能给我一个更好的框架吗?

标签: java algorithm


【解决方案1】:
  1. 您的解决方案是 O(n + m),因为 count(A, max)count(B, max) 调用。 count() 是线性的。

  2. 这不是有效的解决方案。反例:A = [1, 2, 4]B = [3, 5, 1]m = 5。答案是true,因为我们可以将23 交换。您的代码在countB[diff] 上抛出ArrayIndexOutOfBoundsException: -2,因为diff-2。即使您使用例如diff = Math.abs(sumA - sumB) 保护它,该算法仍然不正确,它将返回false

  3. 不用Arrays.fill(p, 0)int默认值是0

  4. 你可以写成p[X[i]]++,而不是p[X[i]] += 1

【讨论】:

  • 感谢您的评论。我将使用 codility 解决方案。
【解决方案2】:

这是(我希望)一个正确的解决方案。 请注意,在检查 dif 不是奇数之后仍然可以进行计数以提高性能。 还要注意,listA 和 listB 数组被用作零位的值,从不使用。这也是为了更好地理解。我们不需要值 0 的出现,但我们需要最大值的出现。

public boolean solution(int[] A, int[] B, int max) {
    int[] listA = new int[max+1];
    int[] listB = new int[max+1];
    int listAsum =0;
    int listBsum=0;

    for(int i = 0; i<A.length; i++){
        listA[A[i]]++;
        listAsum +=A[i];
        listBsum +=B[i];
    }
    int diff = listAsum - listBsum;
    if(diff%2 == 1) return false;
    diff /=2;
    for(int i=0; i<A.length; i++){
        if((B[i] - diff) >= 0  && (B[i]-diff) <= max && listA[(B[i]-diff)] > 0) return true;
    }
    return false;
}

【讨论】:

    【解决方案3】:
    public boolean solution(int[] A, int[] B, int max) {
        int[] count = new int[max + 1];//count(A, max);
        int sum_a = 0; //Arrays.stream(A).sum();
        int sum_b = 0;//Arrays.stream(B).sum();
    
        for (int i = 0; i < A.length; i++) {
            count[A[i]]++;
            sum_a += A[i];
            sum_b += B[i];
        }
        int d = sum_b - sum_a;
        if (d % 2 == 1) return false;
        d /= 2;
    
    
        for (int i = 0; i < A.length; i++) {
            if ((B[i] - d) >= 0 && (B[i] - d) <= max && count[(B[i] - d)]    > 0)
                return true;
        }
        return false;
    }
    public int[] count(int[] X, int max) {
        int[] p = new int[max + 1];
        Arrays.fill(p, 0);
        for (int i = 0; i < X.length; i++) {
            p[X[i]]++;
        }
        return p;
    }
    

    【讨论】:

    • 回答时尝试给出错误原因
    猜你喜欢
    • 2015-02-19
    • 2013-07-02
    • 1970-01-01
    • 2017-01-04
    • 2016-12-20
    • 2020-01-17
    • 1970-01-01
    • 2013-02-13
    • 2011-09-13
    相关资源
    最近更新 更多