I'm solving a programming challenge that essentially consists of finding the highest product of elements in a set.
This is my current solution, and is passing all the test cases but one. The test case that is failing is not available to me, so I kinda have to guess what is wrong with my code.
public static String solution(int[] xs) {
if (xs.length == 1) {
return Integer.toString(xs[0]);
}
Arrays.sort(xs);
BigInteger productOfPositiveIntegers = BigInteger.ONE;
BigInteger productOfNegativeIntegers = BigInteger.ONE;
Vector<BigInteger> negativeIntegers = new Vector<>();
BigInteger result;
boolean areAllElementsZero = true;
for (int element : xs) {
if (element > 0) {
productOfPositiveIntegers = productOfPositiveIntegers.multiply(new BigInteger(Integer.toString(element)));
areAllElementsZero = false;
} else if (element < 0) {
negativeIntegers.add(new BigInteger(Integer.toString(element)));
areAllElementsZero = false;
}
}
if (areAllElementsZero) {
return BigInteger.ZERO.toString();
}
if (negativeIntegers.size() % 2 == 0) {
for (BigInteger element: negativeIntegers) {
productOfNegativeIntegers = productOfNegativeIntegers.multiply(element);
}
} else {
negativeIntegers.remove(negativeIntegers.size() - 1);
for (BigInteger element: negativeIntegers) {
productOfNegativeIntegers = productOfNegativeIntegers.multiply(element);
}
}
if (productOfNegativeIntegers.compareTo(BigInteger.ZERO) == 1) {
result = productOfPositiveIntegers.multiply(productOfNegativeIntegers);
} else {
result = productOfPositiveIntegers;
}
return result.toString();
}
My algorithm is essentially:
- sort numbers from lowest to highest.
- keep track negative numbers in a separate vector.
- multiply all positive numbers
- If the total number of negative numbers is even, multiply them all. If not, drop the lowest negative number and multiply all the negative ones.
- If the product of all the negative numbers is bigger than zero, multiply the product of negative numbers with the product of all positive numbers.
- Return solution.
These are the test cases that I'm passing to my method:
int[] testCase = {2, 0, 2, 2, 0}; // should return "8"
int[] testCase2 = {-2, -3, 4, -5}; // should return "60"
int[] testCase3 = {2, -3, 1, 0, -5}; // should return "30"
int[] testCase4 = {-4, -10, -2, -1, -5}; // should return "400"
int[] testCase5 = {1, 2, 3, 4};
int[] testCase6 = {0, 0, 0}; // should return "0"
int[] testCase7 = {-1}; // should return "-1"
int[] testCase8 = {-1, -1, -1}; // should return "1"
For example the first test case, should return 8 because the highest product would be:
2 * 2 * 2 = 8
Second test case is 60 because:
-4 * -5 * 4 = 60
Last test case is 1 because:
-1 * -1 = 1
My assumption is that my code is taking too long to run for the test case that is failing.
According to the challenge, the highest possible number is 1000, and the highest number of elements in the set would be 50, so the biggest product would be 1E150
When I pass that test case to my program, it runs in less than a second.
So my question is two parts really:
What can I do to speed this up? I'm casting integers to BigIntegers in a loop, so that hurts just to look at it. But I kinda need to do that anyways.
If performance is not the problem, and I'm missing one edge case, which one is it?
Also, if this is not a good question for this community please let me know and I'll be more than happy to remove the question.
negativeIntegers.add(new BigInteger(Integer.toString(element)));
, why notnegativeIntegers.add(BigInteger.valueOf(element));
? \$\endgroup\${ 2, -2 }
? Would be 2 without multiplication, or -4? Could you link to the challenge if possible? \$\endgroup\$