-3

I'm working on a practice program at InterviewStreet and I have a solution that runs with a time of 5.15xx seconds, while the maximum time allowed for a java solution is 5 seconds. Is there anything I can do with what I've got here to get it under 5 seconds? There's also a limit of 256 MB so as near as I can tell this is both the most time and memory efficient solution to the problem...

edit: The possible values for N and K are N <= 10^9 and K <= N, which is why I chose to do everything using BigInteger. The maximum number of trials is 10000. So basically, you input the number of trials, then a pair of integer values for each number of trials, and the program computes the three versions of the binomial coefficient for the equation in the second loop. I figured it would be faster to read everything into the arrays, then process the arrays and put the results into a third array to be processed by the third loop because I figured it might be faster that way. I tried doing everything in the same loop and it ran slower.

I've tried three or four different algorithms for calculating the binomial coefficient (nCr - or n choose r, all are different ways of saying the same thing). Some of the algorithms involve a two dimensional array like c[n][k]. This is the only solution I've submitted that didn't come back with some sort of memory error. The answer needs to be output mod (10 ^ 6) + 3 because the answers of nCr * nCr get pretty huge. A sample run of the program is:

3

4 1
5 2
90 13

2
5
815483

Can't run it on a faster machine because it needs to pass on their machine to count, basically I submit the code and they run it against their test cases, and I have no idea what their test case is, just that the inputs are within the bounds given above.

And the program itself:

import java.math.BigInteger;
import java.util.Scanner;

public class Solution {

public BigInteger nCr(int n, int r) {
    if (r > n ) {
        return BigInteger.ZERO;
    }

    if (r > n / 2) {
        r = n - r;
    }
    BigInteger result = BigInteger.ONE;

    for (int i = 0; i < r; i++) {
        result = result.multiply(BigInteger.valueOf(n - i));
        result = result.divide(BigInteger.valueOf(i + 1));
    }
    return result;
}

public static void main(String[] args) {
    Scanner input = new Scanner( System.in );
    BigInteger m = BigInteger.valueOf(1000003);
    Solution p = new Solution();
    short T = input.nextShort(); // Number of trials
    BigInteger intermediate = BigInteger.ONE;
    int[] r = new int[T];
    int[] N = new int[T];
    int[] K = new int[T];

    short x = 0;

    while (x < T) {
    N[x] = input.nextInt();
    K[x] = input.nextInt();
    x++;
    }

    x = 0;
    while (x < T) {
    if (N[x] >= 3) { 
            r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
        } else {
            r[x] = 0;
    }
    x++;
    }

    x = 0;
    while (x < T) {
    System.out.println(r[x]);
    x++;
    }
}

}

2 Answers2

0

Not entirely sure what the algorithm is trying to accomplish but I'm guessing something with binomial coefficients based on your tagging of the post.

You'll need to check if my suggestion modifies the result but it looks like you could merge two of your while loops:

Original:

while (x < T) {
    N[x] = input.nextInt();
    K[x] = input.nextInt();
    x++;
}

x = 0;
while (x < T) {
if (N[x] >= 3) { 
        r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
    } else {
        r[x] = 0;
    }
    x++;
}

New:

x = 0;
while (x < T) {

//this has been moved from your first while loop
N[x] = input.nextInt();
K[x] = input.nextInt();

if (N[x] >= 3) { 
        r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
    } else {
        r[x] = 0;
    }
    x++;
}
grahamrb
  • 2,159
  • 2
  • 15
  • 22
  • 1
    Also, the `N` and `K` arrays are indexed into several times. Perhaps setting the `N[x]` and `K[x]` values to local variables once per loop and replacing the usages in the `r[x] = ` statement can shave off a few milliseconds. – Cᴏʀʏ May 11 '12 at 22:08
-1

try to run using a profilerm for example the jvisualvm and run this class with

-Dcom.sun.management.jmxremote

attach to the process and start a profile.

Tiago Peczenyj
  • 4,387
  • 2
  • 22
  • 35