Найти в массиве все числа, сумма которых равна нулю

Учитывая массив, последовательные элементы выходного массива, где общая сумма равна 0.

Например:

Для ввода [2, 3, -3, 4, -4, 5, 6, -6, -5, 10],

Вывод [3, -3, 4, -4, 5, 6, -6, -5]

Я просто не могу найти оптимальное решение.

Пояснение 1: для любого элемента в выходном подмассиве должно быть подмножество в подмассиве, которое складывается с элементом до нуля.

Например: для -5 в выходном подмассиве должно присутствовать одно из подмножеств {[-2, -3], [-1, -4], [-5], ....} .

Пояснение 2. Выходной подмассив должен состоять из последовательных элементов.


person Sreejith Ramakrishnan    schedule 20.09.2015    source источник
comment
определите оптимальный... вы забыли это сделать.   -  person Marcus Müller    schedule 20.09.2015
comment
Кроме того, на каком языке?   -  person AJMansfield    schedule 20.09.2015
comment
наименьшее количество исключенных элементов? Будет ли это эквивалентно получению суммы, а затем поиску наименьшего количества элементов, составляющих эту сумму?   -  person Kenny Ostrom    schedule 20.09.2015
comment
@AJMansfield: OP запрашивает алгоритм, а не внедрение   -  person Marcus Müller    schedule 20.09.2015
comment
Подсказка: хорошие ответы даются тем, кто, задав вопрос, проводит следующие пять минут или около того, ожидая комментариев и реагируя на них...   -  person Marcus Müller    schedule 20.09.2015
comment
Итак, вы хотите удалить все x, для которых -x нет в массиве?   -  person AJMansfield    schedule 20.09.2015
comment
возможный дубликат подмассива с нулевой суммой   -  person n. 1.8e9-where's-my-share m.    schedule 20.09.2015
comment
Я пропустил слово последовательный упс. Поэтому оптимальной будет самая длинная последовательность. Похоже, что простой перебор — лучший алгоритм.   -  person Kenny Ostrom    schedule 20.09.2015
comment
@AJMansfield Не ограничиваясь этим. Скажем, у вас есть 3 и -1, -2, они складываются в ноль и должны быть учтены.   -  person Sreejith Ramakrishnan    schedule 20.09.2015
comment
@SreejithRamakrishnan Ваш пример не поддерживает это, вы включаете -4, -6 и 10, но 10 нет в выводе.   -  person AJMansfield    schedule 20.09.2015
comment
Чтобы уточнить: насколько я понимаю, вы хотите удалить все элементы, для которых никакое подмножество других элементов не будет суммироваться с ним до 0. Это правильно?   -  person AJMansfield    schedule 20.09.2015
comment
@AJMansfield Выбор -4 и -6 для покрытия 10 избавит от 6 совпадений. Это сломает подмассив (не последовательный).   -  person Sreejith Ramakrishnan    schedule 20.09.2015
comment
@AJMansfield Да. Именно так. Удалите все элементы, для которых никакое другое подмножество элементов не будет суммироваться с ним до 0.   -  person Sreejith Ramakrishnan    schedule 20.09.2015
comment
@SreejithRamakrishnan Будьте осторожны с подмножеством и подпоследовательностью; Если в выводе нет 10, то это не может быть то, что я сказал. Однако интерпретация, согласующаяся с этим, заключается в том, что вы хотите удалить любой элемент, чтобы никакая подпоследовательность, содержащая его, не равнялась 0.   -  person AJMansfield    schedule 20.09.2015
comment
Ваши разъяснения ничего не проясняют из-за неправильного использования терминологии. Вы сказали, что не можете найти оптимальный способ сделать это, но если вы просто опубликуете написанный вами неоптимальный алгоритм, мы сможем точно понять, о чем вы просите.   -  person AJMansfield    schedule 20.09.2015
comment
Пожалуйста, примите решение. Вы хотите [3, -3, 4, -4, 5, 6, -6, -5] или {[-2, -3], [-1, -4], [-5], ....}?   -  person n. 1.8e9-where's-my-share m.    schedule 20.09.2015
comment
@nm Вы неправильно прочитали. Я имел в виду, что для любого числа n в выходном массиве должно быть подмножество чисел, которое при суммировании с n даст 0.   -  person Sreejith Ramakrishnan    schedule 21.09.2015
comment
Конечно, совершенно невозможно даже эффективно проверить, что это такое подмножество, см. проблему суммы подмножества.   -  person n. 1.8e9-where's-my-share m.    schedule 21.09.2015
comment
@н.м. Предполагая, что все элементы в выходном массиве имеют аналог с отрицательной суммой, я думаю, что невозможно, чтобы любой такой аналог был подмножеством с более чем одним элементом. Если бы такое подмножество существовало, это означало бы, что все числа в этом подмножестве также должны иметь аналоги, но для того, чтобы общая выходная сумма была равна нулю, любое число в выходном массиве может быть только частью one< /i> часть-двойник, и это сделало бы это ограничение недействительным.   -  person גלעד ברקן    schedule 21.09.2015
comment
@גלעדברקן Контрпример: 1,1,1,-1,-1,-1,3.   -  person n. 1.8e9-where's-my-share m.    schedule 21.09.2015
comment
@н.м. OP заявляет в вопросе. Для любого элемента в выходном подмассиве должно быть подмножество в подмассиве, которое складывается с элементом до нуля. Кроме того, последовательные элементы выходного массива, где общая сумма равна 0. Abd в комментарии к вам, для любого числа n должно быть подмножество чисел в выходном массиве, которое при суммировании с n даст 0.   -  person גלעד ברקן    schedule 21.09.2015
comment
@н.м. Общая сумма в вашем встречном примере равна 1+1+1-1-1-1+3 = 3. OP указал последовательные элементы выходного массива, где общая сумма равна 0.   -  person גלעד ברקן    schedule 21.09.2015
comment
@גלעדברקן Очевидно, я не умею считать до нуля. 1+1+1-1-1-1-1-1-1+3 должно работать.   -  person n. 1.8e9-where's-my-share m.    schedule 21.09.2015
comment
@н.м. Ясно спасибо!   -  person גלעד ברקן    schedule 22.09.2015
comment
@SreejithRamakrishnan Когда вы говорите, что хотели бы для любого числа n... подмножество чисел в выходном массиве, которое [дает ноль при суммировании с n], вы имеете в виду непрерывное подмножество? Другими словами, будет ли 1-1+1-1+1-1-1+3-1-1 действительным? (обратите внимание, что аналог для 3 не является смежным)   -  person גלעד ברקן    schedule 23.09.2015
comment
@גלעדברקן Да, смежные. Я думаю, если бы они не были смежными, это была бы проблема rSum, не так ли?   -  person Sreejith Ramakrishnan    schedule 23.09.2015


Ответы (4)


Вот решение на Python, работающее за O(n³):

def conSumZero(input):
    take = [False] * len(input)

    for i in range(len(input)):
        for j in range(i+1, len(input)):
            if sum(input[i:j]) == 0:
                for k in range(i, j):
                    take[k] = True;

    return numpy.where(take, input)

РЕДАКТИРОВАТЬ: теперь более эффективно! (Не уверен, что это вполне O (n²); обновлю, как только закончу вычислять сложность.)

def conSumZero(input):
    take = [False] * len(input)
    cs = numpy.cumsum(input)
    cs.insert(0,0)

    for i in range(len(input)):
        for j in range(i+1, len(input)):
            if cs[j] - cs[i] == 0:
                for k in range(i, j):
                    take[k] = True;

    return numpy.where(take, input)

Разница здесь в том, что я предварительно вычисляю частичные суммы последовательности и использую их для вычисления сумм подпоследовательностей - начиная с sum(a[i:j]) = sum(a[0:j]) - sum(a[0:i]) - вместо того, чтобы повторять каждый раз.

person AJMansfield    schedule 20.09.2015
comment
Мне это нравится, но разве вы не должны начинать с j и заканчивать и работать в обратном порядке, поэтому вы сначала проверяете самые большие решения? Таким образом, вы можете прекратить поиск сразу после нахождения решения. Просто при визуальном осмотре кажется, что вы найдете все возможные решения, пометите их для принятия, а затем объедините их все вместе. Но что, если два разных решения сливаются в результат, который в сумме дает ненулевое значение? - person Kenny Ostrom; 21.09.2015
comment
проверьте это на [1, 2, 3, -6, 1, 2] - person Kenny Ostrom; 21.09.2015
comment
@KennyOstrom Неважно, в каком порядке я проверяю их для этого алгоритма. Правда, если бы я сначала начал с больших, то, вероятно, мог бы сделать ранний выход при проверке меньших, но мне не хочется писать об этом прямо сейчас. Что это делает, так это помечает каждый элемент, который является частью некоторой подпоследовательности с нулевой суммой, а затем берет все отмеченные элементы. Если я отмечу элемент дважды, он все равно будет включен только один раз. - person AJMansfield; 21.09.2015
comment
@KennyOstrom В случае [1 2 3 -6 1 2] будет выведено [1 2 3 -6 1 2], поскольку [1 2 3 -6] в сумме равно 0, а [3 -6 1 2] в сумме равно 0. Эти подпоследовательности включают каждый элемент, поэтому каждый элемент помечается и впоследствии включается в вывод. - person AJMansfield; 21.09.2015
comment
Но вывод не дает в сумме 0, так что вы понимаете мою озабоченность. Вы придерживаетесь исправленного разъяснения, согласно которому каждый элемент имеет подмножество, которое в сумме с ним равно 0, и игнорируете исходное ограничение? - person Kenny Ostrom; 21.09.2015
comment
Я также задаюсь вопросом о последовательном ограничении. Если вы найдете наибольшее решение и сразу же выйдете, вы знаете, что они последовательные, но если вы найдете все решения, то вы получите вывод, который не был последовательным в исходном вводе. [2, -2, 999, -3, 3] -> [2, -2, -3, 3] - person Kenny Ostrom; 21.09.2015
comment
@KennyOstrom Я не так понял вопрос; вопрос плюс комментарии к нему приводят меня к мысли, что это правильная интерпретация проблемы. - person AJMansfield; 21.09.2015
comment
@KennyOstrom На самом деле, читая более свежие комментарии и правки, я думаю, что вы правы, это неправильная интерпретация. - person AJMansfield; 21.09.2015

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

       [2, 3, -3, 4, -4, 5, 6, -6, -5, 10]
sum  0  2  5   2  6   2  7  13  7   2  12

The winner is 2, indexed 1 to 8!

Чтобы также гарантировать точный аналог непрерывного подмассива для каждого числа в выходном массиве, я пока не вижу способа проверить/хэшировать все подпоследовательности сумм в подмассивах-кандидатах, что увеличило бы временную сложность до O(n^2).

person גלעד ברקן    schedule 20.09.2015
comment
Когда вы вычисляете частичную сумму, вы ищете, была ли эта частичная сумма раньше, и это дает вам начало и конец (и, следовательно, длину) подмножества с нулевой суммой. Хранить дольше всего. И вы утверждаете O (1) для поиска с использованием хеш-таблицы (dict). Хорошо, мне это нравится. Может быть, включить 0 в качестве первой суммы, чтобы вы могли обрабатывать ввод, где первая запись равна 0? - person Kenny Ostrom; 21.09.2015
comment
@KennyOstrom спасибо за комментарий. Я думаю, что принял нуль за начальную сумму; впрочем, я добавил. - person גלעד ברקן; 21.09.2015
comment
Если выходная сумма равна 0, то каждый элемент имеет точную копию, состоящую из всей остальной части выходного массива. - person Kenny Ostrom; 21.09.2015
comment
@KennyOstrom не уверен, что вы имеете в виду, у каждого элемента есть точный аналог, состоящий из всей остальной части выходного массива. Можете ли вы привести простой пример? - person גלעד ברקן; 22.09.2015
comment
Вывод представляет собой список чисел, которые в сумме дают 0, например. [50, -5, -10, -15, -20], и вы хотите, чтобы алгоритм определял, существует ли для любого элемента в списке подмножество других элементов, которые составляют этот элемент. Вы беспокоились о временной сложности вычислений. Я сказал, что это O(0), потому что оно уже известно, поэтому вам не нужно его вычислять. - person Kenny Ostrom; 22.09.2015
comment
Возьмите любой элемент, скажем, 50. Точной копией подмассива являются все остальные элементы [-5, -10, -15, -20]. Фраза «точный аналог подмассива» исходит из вашего редактирования ответа выше. - person Kenny Ostrom; 22.09.2015
comment
@KennyOstrom Я думаю, что ОП хотел, чтобы аналог был непрерывным подмассивом. Ваше объяснение, хотя и правильное, не удовлетворяет этому ограничению. - person גלעד ברקן; 23.09.2015

Основываясь на примере, я предположил, что вы хотите найти только те, где 2 значения вместе составляют 0, если вы хотите включить те, которые в сумме дают 0, если вы сложите больше из них вместе (например, 5 + -2 + - 3), то вам нужно будет уточнить ваши параметры немного больше.

Реализация зависит от языка, но вот пример javascript, показывающий алгоритм, который вы можете реализовать на любом языке:

var inputArray = [2, 3, -3, 4, -4, 5, 6, -6, -5, 10];
var ouputArray = [];

for (var i=0;i<inputArray.length;i++){
    var num1 = inputArray[i];

    for (var x=0;x<inputArray.length;x++){
        var num2 = inputArray[x];
        var sumVal = num1+num2;
        if (sumVal == 0){
            outputArray.push(num1);
            outputArray.push(num2);

        }

    }
}
person CodeMonkeyArtist    schedule 20.09.2015
comment
Я почти уверен, что вы не можете просто ожидать найти только пары +x и -x. Вам нужно будет обрабатывать [..., 2, 2, -4, ...] - person Kenny Ostrom; 20.09.2015
comment
Это решение неверно. Если пара чисел не является соседней, это изменит порядок и выведет каждое число дважды. - person AJMansfield; 20.09.2015
comment
@KennyOstrom Пример содержит -4. -6 и 10, но 10 не выводится. - person AJMansfield; 20.09.2015
comment
Я согласен, это не обрабатывает более 2 значений, равных 0. Я добавил это предостережение при редактировании и попросил разъяснений. Да, это приведет к тому, что одно и то же значение будет указано более одного раза, а также не будет соблюдаться исходный порядок сортировки. Если это важные функции, их можно переработать, я просто сделал их простыми, так как не было очень четкого определения желаемого. - person CodeMonkeyArtist; 20.09.2015
comment
Я также пропустил слово последовательно выше. Может ли ОП уточнить, что именно требуется, прежде чем я приложу какие-либо усилия к его переработке для добавления более двух значений, только последовательных, без дубликатов, порядка сортировки и т. Д. - person CodeMonkeyArtist; 20.09.2015

Это проблема, которую вы пытаетесь решить?

Учитывая последовательность , найдите максимизация такой, что

Если да, то вот алгоритм ее решения:

let $U$ be a set of contiguous integers
for each contiguous $S\in\Bbb Z^+_{\le n}$
    for each $\T in \wp\left([i,j)\right)$
      if $\sum_{n\in T}a_n = 0$
        if $\left|S\right| < \left|U\left$
          $S \to u$

вернуть $U$

(Будет обновлен с полным латексом, как только у меня будет такая возможность.)

person AJMansfield    schedule 21.09.2015