Codility - 计数元素课程:最快的算法交换

时间:2014-11-15 11:07:31

标签: java algorithm

我是studying Codility chapter 2 : Counting elements

我试着进行练习,我想我有一个很好的解决方案O(n)。这是一个有效的解决方案? 这是在课程中提出的最佳解决方案更好的解决方案吗?

问题:给定一个整数m(1 m 1 000 000)和两个非空的,零索引的n个整数的数组A和B,a0,a1,..., a-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;

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

 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;
}

3 个答案:

答案 0 :(得分:2)

  1. 由于O(n + m)count(A, max)次调用,您的解决方案为count(B, max)count()是线性的。

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

  3. 您不需要执行Arrays.fill(p, 0)int默认值为0

  4. 您可以写p[X[i]] += 1代替p[X[i]]++

答案 1 :(得分:0)

这是(我希望)一个正确的解决方案。 请注意,在检查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;
}

答案 2 :(得分:0)

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;
}