Array whose values are the product of every other integer I was asked the following interview question over the phone:


  Given an array of integers, produce an array whose values are the
  product of every other integer excluding the current index.
  
  Example: 

[4, 3, 2, 8] -&gt; [3*2*8, 4*2*8, 4*3*8, 4*3*2] -&gt; [48, 64, 96, 24]



and I gave the following answer

import java.math.BigInteger;
import java.util.Arrays;

public class ProductOfAnArray {

    public static void main(String[] args) {

        try {
            System.out.println(Arrays.toString(ProductOfAnArray
                    .calcArray(new int[] { 4, 3, 2, 8 })));
            System.out.println(Arrays.toString(ProductOfAnArray
                    .calcArray(new int[] { 4, 0, 2, 8 })));
            System.out.println(Arrays.toString(ProductOfAnArray
                    .calcArray(new int[] { 4, 0, 2, 0 })));
            System.out.println(Arrays.toString(ProductOfAnArray
                    .calcArray(new int[] {})));
            System.out
                    .println(Arrays.toString(ProductOfAnArray
                            .calcArray(new int[] { 4, 3, 2, 8, 3, 2, 4, 6, 7,
                                    3, 2, 4 })));
            System.out
                    .println(Arrays.toString(ProductOfAnArray
                            .calcArray(new int[] { 4, 3, 2, 8, 3, 2, 4, 6, 7,
                                    3, 2, 4 })));
            System.out.println(Arrays.toString(ProductOfAnArray
                    .calcArray(new int[] { 4432432, 23423423, 34234, 23423428,
                            4324243, 24232, 2342344, 64234234, 4324247,
                            4234233, 234422, 234244 })));
        } catch (Exception e) {
            // debug exception here and log.
        }
    }

    /*
     * Problem: Given an array of integers, produce an array whose values are
     * the product of every other integer excluding the current index.
     * 
     * Assumptions. Input array cannot be modified. input is an integer array
     * "produce an array" - type not specified for output array
     * 
     * Logic explanation:
     * 
     * Assume we have array [a,b,c,d] Let multiple be multiple of each element
     * in array. Hence multiple = 0 if one of the element is 0; To produce the
     * output. Ans at i -&gt; multiple divided by the value at i. if 2 numbers are
     * 0 then entire output will be 0 because atleast one 0 will be a multiple
     * if 1 number is 0 then every thing else will be 0 except that index whole
     * value is to be determined
     * 
     */
    public static BigInteger[] calcArray(final int[] inp) throws Exception {
        if (inp == null)
            throw new Exception("input is null");

        int cnt = 0;
        BigInteger multiple = new BigInteger("1");
        boolean foundZero = false;

        for (int i : inp) {
            if (i == 0) {
                cnt++;
                foundZero = true;
                if (cnt &lt; 2)
                    continue;
                else
                    break;
            }
            multiple = multiple.multiply(BigInteger.valueOf(i));
        }

        BigInteger ans[] = new BigInteger[inp.length];

        for (int i = 0; i &lt; inp.length; i++) {
            if (foundZero) {
                if (cnt &lt; 2) {
                    ans[i] = (inp[i] == 0) ? multiple : new BigInteger("0");
                } else {
                    ans[i] = new BigInteger("0");
                }
            } else {
                ans[i] = multiple.divide(BigInteger.valueOf(inp[i]));
            }
        }
        return ans;
    }

}


But I was not selected. I would like to get feedback on my answer and see what's wrong.
For starters, you have very weird line breaks:

System.out
        .println(Arrays.toString(ProductOfAnArray
                .calcArray(new int[] { 4, 3, 2, 8, 3, 2, 4, 6, 7,
                        3, 2, 4 })));


That's not layout, that's obfuscation! When dealing with long method chains, it may be preferable to break before each method invocation:

someObject
  .thisIs()
  .aFluid()
  .interface();


but that's not the case here, and this layout does not increase readability. Instead, break after the opening paren of the argument list:

System.out.println(
    Arrays.toString(ProductOfAnArray.calcArray(new int[] {
        4, 3, 2, 8, 3, 2, 4, 6, 7, 3, 2, 4
    }))
);


or something like that. Note that you could have written this as

System.out.println(
    Arrays.toString(ProductOfAnArray.calcArray(
        4, 3, 2, 8, 3, 2, 4, 6, 7, 3, 2, 4
    ))
);


(i.e. without the explicit array) when declaring your function with varargs: calcArray(int... inp).

The next question is why you are returning an array – a List&lt;BigInteger&gt; would be more flexible – arrays have little use in modern Java (the usage of varargs implies arrays, and high-performance code may need them. But in all other cases, they are too inflexible – e.g. arrays and generics don't work together).

But why BigInteger? Yes, you don't want to overflow, but we can assume that your interviewers would be content with an int. If you want to allow larger numbers, the first step would be long. Big Integers are truly awkward to use and necessarily less performant that native types, so I would avoid them wherever possible.

Your code inside calcArray is unnecessarily clever. Let's look at this loop:

for (int i : inp) {
    if (i == 0) {
        cnt++;
        foundZero = true;
        if (cnt &lt; 2)
            continue;
        else
            break;
    }
    multiple = multiple.multiply(BigInteger.valueOf(i));
}


Notice that foundZero is equivalent to cnt &gt; 0, and that you aren't using braces around the bodies of the inner if/else. Your continue is rather confusing, and the following expresses the control flow much better:

for (int i : inp) {
    if (i != 0) {
        multiple = multiple.multiply(BigInteger.valueOf(i));
    }
    else {
        cnt++;
        if (cnt &gt;= 2) {
            break;
        }
    }
}


This conditional in the next loop is also too complex, and could be simplified to

if (cnt &lt; 2 &amp;&amp; inp[i] == 0) {
    ans[i] = multiple;
} else {
    ans[i] = new BigInteger("0");
}


When applying these criticisms, the Simplest Thing That Could Work might be this:

public static List&lt;Long&gt; specialProduct(int... numbers) {
    long product = 1;
    int zeroesCount = 0;
    for (int n : numbers) {
        if (n != 0) {
            product *= n;
        }
        else {
            zeroesCount++;
        }
    }

    List&lt;Long&gt; output = new ArrayList&lt;&gt;(numbers.length);

    switch (zeroesCount) {
    case 0:
        // with no zeroes, we don't have to perform any checks
        for (int n : numbers) {
            output.add(product / n);
        }
        break;
    case 1:
        // with one zero, the all others will become zero too
        for (int n : numbers) {
            if (n == 0) {
                output.add(product);
            }
            else {
                output.add(0L);
            }
        }
        break;
    default:
        // two or more zeroes make everything zero
        for (int i = 0; i &lt; numbers.length; i++) {
            output.add(0L);
        }
        break;
    }

    return output;
}


Oh, and naming! Have vocals become so precious that we must write cnt instead of count? Must we write ans instead of answer if you can actually write a long word like multiple? And what the heck is inp?

Your code is not bad, but it isn't good, and could certainly have been written better. The next time, maybe :)