7

I'm sorry for deleting the original question, here it is: We have a bag or an array of n integers, we need to find the product of each of the (n-1) subsets. e.g:

S = {1, 0, 3, 6}
ps[1] = 0*3*6 = 0;
ps[2] = 1*3*6 = 18; etc.

After discussions, we need to take care of the three cases and they are illustrated in the following:

1. S is a set (contains one zero element)
  for i=1 to n
    if s[i]=0
      sp[i] = s[1] * s[2] * ...* s[i-1] * s[i+1] *.....*s[n]
    else
      sp[i] = 0;

2. S is a bag (contains more than one zero element) 
  for i=1 to n
      sp[i] = 0;

3. S is a set (contains no zero elements)
   product = 1
   for i=1 to n
     product *= s[i];
   for i=1 to n
     sp[i] = product / s[i];

Thanks.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
guirgis
  • 1,133
  • 2
  • 14
  • 17
  • 1
    `O(N)` solution exists without using division: http://stackoverflow.com/questions/2680548/interview-q-given-an-array-of-numbers-return-array-of-products-of-all-other-num/ – polygenelubricants Apr 22 '10 at 08:33
  • related question: http://stackoverflow.com/questions/56215/interesting-interview-questions – jfs May 02 '10 at 21:17
  • Hi, is it possible to extend it to case for any subset of an array? http://stackoverflow.com/questions/28804120/find-product-of-any-combination-of-elements-from-a-list/28804230?noredirect=1#comment45882003_28804230 – meta_warrior Mar 02 '15 at 09:02

5 Answers5

13

If the set is very large, it may be convenient to:

  • compute the product P of all the elements beforehand, and then
  • for each element x, obtain a (n-1) product as P/x

If the set contains zero (i.e. P=0, x=0), you must deal with it as a special case.

EDIT. Here is a solution in Scheme, taking into account andand's answer. I'm a complete beginner - can someone help me improve the following code (make it more efficient, more readable, more lisp-ish)? (Feel free to edit my answer.)

#!/usr/bin/env guile !#
(use-modules (ice-9 pretty-print))

(define (count-zeros l)
    (cond ((null? l) 0)
          ((= 0 (car l)) (+ 1 (count-zeros (cdr l))))
          (else (count-zeros (cdr l)))))

(define (non-zero-product l)
    (define (non-zero-product-loop l product)
        (cond ((null? l) product)
              ((= 0 (car l)) (non-zero-product-loop (cdr l) product))
              (else (non-zero-product-loop (cdr l) (* (car l) product)))))
    (non-zero-product-loop l 1))

(define (n-1-products l)
    (let ((nzeros (count-zeros l)))
         (cond ((> nzeros 1)
                   (map (lambda (x) 0) l))
               ((= 1 nzeros)
                   (map (lambda (x) (if (= 0 x) (non-zero-product l) 0)) l))
               (else 
                   (map (lambda (x) (/ (non-zero-product l) x)) l)))))

(pretty-print (n-1-products '(1 2 3 4 5)))
(pretty-print (n-1-products '(0 1 2 3 4)))
(pretty-print (n-1-products '(0 1 2 3 0)))
Federico A. Ramponi
  • 46,145
  • 29
  • 109
  • 133
  • I know your idea, my problem is that special case (zero elements), what will i do then, do i consider a different problem? But what happens when the set contains many zero elements? i think we need a generic solution that apply to all values. – guirgis Apr 19 '10 at 18:35
  • 2
    @guirgis - A set is a collection of distinct elements. It can only have one instance of any particular element. If it can contain more than one instance of a particular element, it is a multiset (or bag). If you have a bag with more than one zero, the result is trivial -- think about it. – tvanfosson Apr 19 '10 at 18:38
  • I think @Federico's solution is generic and applies to all the values encompassed by the example in your question. Bear in mind that if you have a set of integers then 0 can only be a member of the set once; a set cannot contain many 0 elements. – High Performance Mark Apr 19 '10 at 18:38
  • @guirgis - the most obvious way to handle a set with a zero is simply to mark all of the other results as zero when you encounter one and continue building the product without that element -- i.e., devolve to the special case of calculating just the one subset product for the subset omitting the single zero value. – tvanfosson Apr 19 '10 at 18:41
  • Firstly, i'm sorry for misusing the word "Set", i should have used a "bag" or "array". Secondly, Thanks for your ideas, i'm trying to understand it. – guirgis Apr 19 '10 at 19:03
  • Oh, If the bag contains more than one zero, then all the subsets products will be "Zeros". And if it contains one zero then all the subsets except the one of the zero element will be zeros and the one of the zero element will be the product of the rest of the elements. Thank you tvanfosson and all the guys for your hints although it made me feel kinda stupid. – guirgis Apr 19 '10 at 19:21
11

You need to explicitly consider the three cases:

1) No zeros: Precompute the product of all of the elements and divide out the desired set element from that product.

2) One zero: Precompute the product of the non-zero elements. The answer is always 0 except when you remove the single zero element, in which case it's the precomputed product.

3) More than one zero: The answer is always 0.

This assumes that you have a data type that can contain the products... that is, you need to be careful that your product doesn't exceed the maximum value of the type you're using to store it.

For the actual implementation, always precompute the product of the non-zero elements and keep track of how many zeros there are. If the "set" is dynamic (its values change) you'll need to update the product and the zero count. When asked for a particular subset product, consider the various cases and act accordingly.

andand
  • 17,134
  • 11
  • 53
  • 79
2
Set product = 1;
for item in set:
   if item index == argument index
      ignore
   else
      product *= item

If I understand your question, this is the trivial solution. It should be easy to implement in any programming language.

Stefan Kendall
  • 66,414
  • 68
  • 253
  • 406
  • You understood me, and your algorithm is completely correct, but the problem is that to compute it for all subsets, the complexity will be of O(n^2), we're looking for an optimum solution. – guirgis Apr 19 '10 at 18:38
  • 1
    Ah. You didn't ask for an optimal solution :) – Stefan Kendall Apr 19 '10 at 18:41
2

You can solve this in O(N), using O(1) additional space (not counting the O(N) output array), without even using division. Here's the algorithm in Java.

static int[] products(int... nums) {
    final int N = nums.length;
    int[] prods = new int[N];
    int pi = 1;
    for (int i = 0; i < N; i++) {
        prods[i] = pi;
        pi *= nums[i];
    }
    int pj = 1;
    for (int j = N-1; j >= 0; j--) {
        prods[j] *= pj;
        pj *= nums[j];
    }
    return prods;
}

//...
System.out.println(
   Arrays.toString(products(1, 2, 3, 4, 5))
); // prints "[120, 60, 40, 30, 24]"

See also

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
0

Assuming you can use Python:

You can use the combinations method from the itertools module to lazily generate the various subsets of the set in question. Once you have that, you can use reduce and operator.mul to generate the product of each one.

Hank Gay
  • 70,339
  • 36
  • 160
  • 222
  • Thanks Hank, a pretty implementation, but i think i kinda need the algorithm not the implementation. – guirgis Apr 19 '10 at 19:00