哪个测试用例可以破解Incl / Excl原理挑战的解决方案?

时间:2015-11-02 09:41:02

标签: java algorithm

我正在编写一个编程挑战,其中一个问题涉及一个包含/排除原则问题,我认为我已经解决了这个问题,但一些测试用例仍然失败了。我无法想到它们可能是什么(其中2个测试用例失败,但它们没有显示输出)。你能给我一些关于它们可能是什么的想法吗?

原始问题:

  K毛毛虫正在通过每片毛虫的N片叶子吃东西   所有毛毛虫都以独特的顺序从一片叶子落到另一片叶子   在0号位置的树枝处,落在两片之间的叶子上   每个履带j都具有相关的跳跃数Aj。一个   毛茸茸的跳跃数j吃叶子的位置   j的倍数。它将以j,2j,3j ......的顺序进行。直到它   到达叶子的末端,它停止并建立它的茧。特定   一组K元素K <-15,N <= 10 ^ 9,我们需要确定数字   未吃的叶子。

     

输入:

     

N =未吃叶子数量K =毛虫数量A =整数数组   跳数

     

输出:

     

整数nu。未吃的叶子

     

示例输入:

     

10 3 2 4 5

     

输出:

     

4

     

说明:

     

[2,4,5]是一个j成员跳跃数,所有叶子是多个   吃掉2,4和5,留下1,3,7,9叶,因此没有。 4

我的解决方案:

static int countUneatenLeaves(int N, int[] A) {
    int total = 0;
    for (int i = 0; i < A.length; i++) {
        int multiplier = (int) Math.pow(-1, i);
        total += multiplier * combination(A, i + 1, N);
    }
    return N - total;
}

public static int combination(int[] elements, int K, int num) {

    // get the length of the array
    // e.g. for {'A','B','C','D'} => N = 4 
    int N = elements.length;

    // get the combination by index 
    // e.g. 01 --> AB , 23 --> CD
    int combination[] = new int[K];

    // position of current index
    //  if (r = 1)              r*
    //  index ==>       0   |   1   |   2
    //  element ==>     A   |   B   |   C
    int r = 0;
    int index = 0;
    int total = 0;
    while (r >= 0) {
        // possible indexes for 1st position "r=0" are "0,1,2" --> "A,B,C"
        // possible indexes for 2nd position "r=1" are "1,2,3" --> "B,C,D"

        // for r = 0 ==> index < (4+ (0 - 2)) = 2
        if (index <= (N + (r - K))) {
            combination[r] = index;

            // if we are at the last position print and increase the index
            if (r == K - 1) {

                //do something with the combination e.g. add to list or print
                total += calc(combination, elements, num);
                index++;
            } else {
                // select index for next position
                index = combination[r] + 1;
                r++;
            }
        } else {
            r--;
            if (r > 0) index = combination[r] + 1;
            else index = combination[0] + 1;
        }
    }
    return total;
}

private static int calc(int[] combination, int[] elements, int num) {

    int eaten = 0;
    if (combination.length == 1) {
        eaten = (int) Math.floor(num / elements[combination[0]]);
    } else {
        int lcm = lcm(elements[combination[0]], elements[combination[1]]);
        for (int i = 2; i < combination.length; i++) {
            lcm = lcm(lcm, elements[combination[i]]);
        }
        eaten = Math.abs((int) Math.floor(num / lcm));
    }
    return eaten;
}

private static int lcm(int a, int b) {
    return a * (b / findGCD(a, b));
}

private static int findGCD(int number1, int number2) {
    //base case
    if (number2 == 0) {
        return number1;
    }

    return findGCD(number2, number1 % number2);
}

我自己尝试了很多测试输入但未能找到它打破的情况。我怀疑测试失败涉及大N,好像我采用简单的暴力方法,相同的测试用例会因超时而失败。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我认为你应该使用long而不是int。因为A的元素可以接近10 ^ 9。所以当num gcd(a,b)很小时,例如1,lcm(a,b)= a * b可能大于0x7FFFFFFF,所以答案是不正确的。