Предыдущее | Следующее

Улыбка
Задача из ru_programming: в заданном массиве целых чисел найти (непустой) отрезок с максимальной суммой. Массив разрешается просматривать всего один раз. Дополнительную память (массивы) использовать нельзя.

Нетерпеливые могут посмотреть решение здесь.

Comments

( 15 комментариев — Оставить комментарий )
[info]spamsink wrote:
27 Апр, 2009 21:19 (UTC)
Эта задача - чуть ли не единственное, что я помню из занятий по программированию в Керосинке. Очень понравилось в свое время.
[info]a_shen wrote:
27 Апр, 2009 21:50 (UTC)
если разрешать отрезки нулевой длины

k:=0; lastmax:=0; totalmax:=0;
{lastmax=максимальная сумма по отрезкам, примыкающим к концу a[1..k], totalmax=максимальная сумма по всем отрезкам}
while (k not equal to n) do begin
k:=k+1;
lastmax:=max(lastmax+a[k],0);
totalmax:=max(lastmax,totalmax);
end;


[info]ramlamyammambam wrote:
28 Апр, 2009 06:15 (UTC)
Требуется сам отрезок, а не его сумма. Отрезки нулевой длины тоже нехорошо.
[info]a_shen wrote:
28 Апр, 2009 07:31 (UTC)
ну тогда
k:=1;
lastmax:=(a[1],1,1);
totalmax:=lastmax;
{last,totalmax = (value, first, last)
for maximal sums at the end and in total}
while (k not equal to n) do begin
k:=k+1;
if lastmax.1 less than 0 then begin
lastmax.1:=a[k];
lastmax.2:=k;
lastmax.3:=k;
end else begin
lastmax.1 := lastmax.1+a[k];
lastmax.3 := k;
end;
if lastmax.1 GT totalmax.1 then begin
totalmax:=lastmax;
end;
end;
[info]dz wrote:
27 Апр, 2009 22:19 (UTC)
ну - три переменных-то можно? в одной храним текущую сумму - на каждом сдвиге окна приплюсовываем входящее значение и вычитаем "покинутое". ещё пара - чтобы хранить известный максимум и номер позиции, с которой начинается его окно.
[info]tnt23 wrote:
28 Апр, 2009 05:53 (UTC)
Вот требование не использовать память меня подкосило - а как без переменных указать хотя бы начало и конец отрезка, я не очень представляю.
[info]ramlamyammambam wrote:
28 Апр, 2009 06:10 (UTC)
Переменные можно. Нельзя требовать дополнительную память, пропорциональную длине входного массива.
[info]v1adis1av wrote:
28 Апр, 2009 10:00 (UTC)
А в сам массив писать можно? или он read-only?
[info]ramlamyammambam wrote:
28 Апр, 2009 16:54 (UTC)
Нет, писать его не разрешается. Можно считать, что никаких массивов нет, а входные данные поступают последовательно по одному.
[info]ramlamyammambam wrote:
28 Апр, 2009 06:12 (UTC)
Переменные можно. Но так просто не получается, попробуй. :)
Чтобы вычитать покинутое, придётся крутить цикл в цикле и иметь массив сумм для всех длин отрезков от 1 до N.
[info]dz wrote:
28 Апр, 2009 09:30 (UTC)
а, понял - нужно найти отрезок произвольной длины...
[info]tnt23 wrote:
28 Апр, 2009 05:52 (UTC)
Дык отрезок длиной в сам массив и будет искомым :) или числа в массиве могут быть отрицательными?
[info]ramlamyammambam wrote:
28 Апр, 2009 06:08 (UTC)
Могут быть отрицательными, конечно.
[info]v1adis1av wrote:
28 Апр, 2009 14:31 (UTC)
Пусть S(i) -- сумма элементов массива от 0 до i. Тогда границами искомого отрезка будет слева -- точка i(Min), где достигается глобальный минимум функции S(i), справа -- точка i(Max) глобального максимума. Однако этот подход неприменим к случаю, когда глобальный минимум находится справа от гл.максимума. Так что задача сложнее, чем кажется на первый взгляд: нужно найти "почти глобальный" минимум i(min1) на всей области слева от глобального максимума i(Max) и "почти глобальный" максимум i(max1) на всей области справа от глобального минимума i(Min), затем сравнить Max-min1 и max1-Min. Тот из этих двух отрезков, для которого разность больше, и будет искомым (если гл.минимум слева от гл.максимума, то эти два отрезка суть один). Ессно, всё это можно сделать за один проход по массиву.
[info]ramlamyammambam wrote:
28 Апр, 2009 16:57 (UTC)
Совершенно верно. И не забыть про случай, когда все элементы массива отрицательные.
( 15 комментариев — Оставить комментарий )