Поиск произведения каждого из (n-1) подмножеств заданного массива

Прошу прощения за удаление исходного вопроса, вот он: У нас есть сумка или массив из n целых чисел, нам нужно найти произведение каждого из (n-1) подмножеств. например:

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

После обсуждений нам нужно позаботиться о трех случаях, и они проиллюстрированы следующим образом:

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];

Спасибо.

Ответ 1

Если множество очень велико, может быть удобно:

  • заранее вычислить продукт P всех элементов, а затем
  • для каждого элемента x, получим (n-1) произведение в виде P/x

Если множество содержит нуль (т.е. P = 0, x = 0), вы должны иметь дело с ним как особый случай.

ИЗМЕНИТЬ. Вот решение на Схеме, учитывая и ответ. Я полный новичок - может ли кто-нибудь помочь мне улучшить следующий код (сделать его более эффективным, более читаемым, более lisp -ish)? (Не стесняйтесь редактировать мой ответ.)

#!/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)))

Ответ 2

Вам нужно явно рассмотреть три случая:

1) Нет нулей: Прекоммутируйте продукт всех элементов и разделите желаемый элемент набора из этого продукта.

2) Один ноль: Прекоммутируйте произведение ненулевых элементов. Ответ всегда 0, за исключением случаев, когда вы удаляете одиночный нулевой элемент, и в этом случае он представляет собой предварительно вычисленный продукт.

3) Более одного нуля: Ответ всегда равен 0.

Это предполагает, что у вас есть тип данных, который может содержать продукты... то есть вы должны быть осторожны, чтобы ваш продукт не превышал максимальное значение типа, используемого вами для его хранения.

Для реальной реализации всегда прекомпретируйте произведение ненулевых элементов и отслеживайте, сколько нулей существует. Если "set" является динамическим (его значения изменяются), вам нужно будет обновить продукт и подсчитать нуль. При запросе конкретного продукта подмножества рассмотрите различные случаи и действуйте соответствующим образом.

Ответ 3

Set product = 1;
for item in set:
   if item index == argument index
      ignore
   else
      product *= item

Если я понимаю ваш вопрос, это тривиальное решение. Это должно быть легко реализовать на любом языке программирования.

Ответ 4

Вы можете решить это в O(N), используя O(1) дополнительное пространство (не считая массива вывода O(N)), даже не используя деление. Вот алгоритм в 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]"

См. также

Ответ 5

Предполагая, что вы можете использовать Python:

Вы можете использовать combinations метод из модуля itertools для ленивого создания различных подмножеств заданного набора. После этого вы можете использовать reduce и operator.mul для создания продукта каждого из них.