Поиск непрерывных подмассивов в Excel - вариант алгоритма Кадане?

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

Простой пример:

Index, Value
0   0
1   0
2   3
3   4
4   2
5   6
6   0
7   0
8   0
9   2
10  3
11  0

В приведенном выше примере самый большой последовательный подмассив, не прерываемый 0, находится от индекса 2 до индекса 5 включительно, а сумма этого подмассива равна 15.

Таким образом, для следующих пороговых значений 20, 10 и 4 результаты должны быть FALSE, TRUE и TRUE соответственно.

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

Я подозреваю, что эта проблема является разновидностью алгоритма Кадане, но я не могу понять, как его настроить.

Дополнительная сложность заключается в том, что я должен выполнять этот анализ в Excel или Google Sheets, и я не могу использовать для этого сценарии — только встроенные формулы.

Я не уверен, что это можно сделать, но я был бы признателен за любой вклад.


person Dexmoody    schedule 21.04.2020    source источник
comment
Глядя на этот hackernoon.com/kadanes-algorithm-explained-50316f4fd8a6, должно быть довольно легко реализовать его в листах Excel или Google, используя вспомогательный столбец, с дополнительным тестом, который должен сбрасывать промежуточный итог, если текущий элемент равен нулю. Единая формула была бы довольно сложной задачей.   -  person Tom Sharpe    schedule 21.04.2020
comment
На самом деле, поскольку у вас все положительные значения, алгоритм просто становится «if x[i]›0 sum=sum+x[i] else sum=0»   -  person Tom Sharpe    schedule 21.04.2020


Ответы (3)


Начните с

=B2

in c2

тогда поставь

=IF(B3=0,0,B3+C2)

в C3 и скопируйте вниз.

введите здесь описание изображения

ИЗМЕНИТЬ 1

Если вы искали решение для таблиц Google, попробуйте что-то вроде этого:

=ArrayFormula(max(sumif(A2:A,"<="&A2:A,B2:B)-vlookup(A2:A,{if(B2:B=0,A2:A),sumif(A2:A,"<="&A2:A,B2:B)},2)))

Предполагается, что числа в столбце B начинаются с нуля: в противном случае необходимо добавить Iferror. По сути, это реализация формулы массива метода студента @Gary.

ИЗМЕНИТЬ 2

Вот формула Google Sheets, переведенная обратно в Excel. Это дает вам альтернативу, если вы не хотите использовать смещение:

=MAX(SUMIF(A2:A13,"<="&A2:A13,B2:B13)-INDEX(SUMIF(A2:A13,"<="&A2:A13,B2:B13),N(IF({1},MATCH(A2:A13,IF(B2:B13=0,A2:A13)))))) 

(вводится как формула массива).

Комментарий

Возможно, настоящая проблема заключается в том, чтобы найти формулу, которая работает как в таблицах Excel, так и в таблицах Google, потому что:

  • Vlookup не работает так же, как в Excel
  • Комбинация смещения/промежуточного итога не работает в таблицах Google.
  • Комбинация index/match с n(if{1}... не работает в таблицах Google.
person Tom Sharpe    schedule 21.04.2020
comment
Это здорово, спасибо, @Tom Sharpe. Это, безусловно, самое простое решение этой проблемы. Мне немного стыдно, что я не додумался до этого сам. - person Dexmoody; 22.04.2020
comment
Поскольку мне нужно сделать это в более чем 30 столбцах, я бы предпочел избегать вспомогательного столбца - ниже я опубликую решение, которое достигает этого. - person Dexmoody; 22.04.2020
comment
Вы упомянули Google Sheets в качестве альтернативы: добавили решение Google Sheets в мой ответ. Могу ли я добавить тег Google Sheets к вашему вопросу? - person Tom Sharpe; 22.04.2020
comment
Очень интересно, спасибо! У меня еще не было возможности проверить это, но скоро сделаю это и отчитаюсь! - person Dexmoody; 23.04.2020

Имея данные в столбцах A и B, убедитесь, что столбец B заканчивается 0. Затем в C2 введите:

=ЕСЛИ(И(B3=0,B2‹>0),СУММ(B$1:$B2)-МАКС($C$1:C1),"")

и скопируйте вниз:

введите здесь описание изображения

В столбце C перечислены суммы последовательных ненулевых значений. В другой ячейке введите что-то вроде:

=MAX(C:C)>19

где 19 — значение критерия.

Вы можете избежать столбца «помощник», используя UDF VBA.

РЕДАКТИРОВАНИЕ №1:

Используйте это вместо этого:

=IF(AND(B3=0,B2<>0),SUM(B$1:$B2)-SUM($C$1:C1),"")
person Gary's Student    schedule 21.04.2020
comment
Должно быть = ЕСЛИ (И (B3 = 0, B2‹›0), СУММ(B$1:$B2)-СУММ($C$1:C1)) @Студент Гэри? - person Tom Sharpe; 21.04.2020
comment
@TomSharpe Еще раз спасибо! - person Gary's Student; 21.04.2020
comment
Спасибо, Гэри Студент. Отличное решение, которое решает проблему. Спасибо также за ваше предложение в отношении избегания вспомогательного столбца. Я нашел другое решение, которое достигает этого без VBA, которое я опубликую ниже. - person Dexmoody; 22.04.2020

Спасибо @Tom Sharpe и @Gary's Student за ответ на вопрос.

Хотя я, по общему признанию, не указал это в вопросе, я бы предпочел получить решение без вспомогательного столбца, потому что мне нужно выполнить эту операцию для более чем 30 последовательных столбцов. Я просто не думал, что это возможно в Excel.

Полная заслуга пользователя XOR LX на форуме Excel за разработку этого решения. Это взорвало мой мозг, и мне потребовалась большая часть часа, чтобы собраться с мыслями, но это, безусловно, очень креативно. Я никак не мог придумать это сам. Повторная публикация его здесь для пользы всех, кто изучает это.

Скопируйте и вставьте таблицу из моего первоначального вопроса в пустой лист Excel, чтобы заголовки отображались в (A1:B1), а значения отображались в (A2:B13).

Затем введите эту формулу как формулу массива (ctrl+shift+enter), которая дает максимальную сумму всех непрерывных подмассивов:

=MAX(SUBTOTAL(9,OFFSET(B2,A2:A14,,-FREQUENCY(IF(B2:B13,A2:A13),IF(B3:B14=0,A2:A13,0))-1)))

Обратите внимание на преднамеренное смещение, чтобы включить одну дополнительную строку ниже конца набора данных.

person Dexmoody    schedule 22.04.2020
comment
Это действительно выглядит очень аккуратно - я попробую позже, чтобы понять, как это делается. Я смутно думал, что частота может помочь, но не мог понять, как, хотя я думаю, что вариант ответа студента @Gary также может работать как единая формула в таблицах Google и / или O365. - person Tom Sharpe; 22.04.2020