Old, but very cool, I was asked about this at an interview and I saw several solutions, but this is my favorite, as taken from http://www.polygenelubricants.com/2010/04/on-all-other-products-no-division .html
static int[] products(int... nums) { final int N = nums.length; int[] prods = new int[N]; java.util.Arrays.fill(prods, 1); for (int // pi----> * <----pj i = 0, pi = 1 , j = N-1, pj = 1 ; (i < N) & (j >= 0) ; pi *= nums[i++] , pj *= nums[j--] ) { prods[i] *= pi ; prods[j] *= pj ; System.out.println("pi up to this point is " + pi + "\n"); System.out.println("pj up to this point is " + pj + "\n"); System.out.println("prods[i]:" + prods[i] + "pros[j]:" + prods[j] + "\n"); } return prods; }
This is what happens if you write prods [i] for all iterations, you will see the following calculation
prods[0], prods[n-1] prods[1], prods[n-2] prods[2], prods[n-3] prods[3], prods[n-4] . . . prods[n-3], prods[2] prods[n-2], prods[1] prods[n-1], prods[0]
therefore, each finger [i] gets hit twice, one from head to tail and once from tail to head, and both these iterations accumulate the product as they move to the center, so itβs easy to see that we get exactly what we need , we just need to be careful and see that it skips the element itself and that where it becomes difficult. the key lies in
pi *= nums[i++], pj *= nums[j--]
in a loop cycle condition, and not in a body that does not occur until the end of the iteration. Thus, for prods[0], it starts with 1 * 1, and then pi gets the value 120 after, so prods [0] skips the first elements of prods[1], it 1 * 120 = 120, and then pi is set to 120 * 60 after so on and so forth