Найти наибольшую сумму подпоследовательности


11

По заданной последовательности целых чисел найдите наибольшую сумму подпоследовательности (целые числа в последовательных позициях) последовательности. Подпоследовательность может быть пустой (в этом случае сумма равна 0).

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

Я написал небольшой генератор для вас:

#include <stdio.h>
#include <assert.h>


/* From http://en.wikipedia.org/wiki/Random_number_generation */
unsigned m_w;
unsigned m_z;

unsigned get_random()
{
  m_z = 36969 * (m_z & 65535) + (m_z >> 16);
  m_w = 18000 * (m_w & 65535) + (m_w >> 16);
  return (m_z << 16) + m_w;  /* 32-bit result */
}

int main(int argc, char **argv)
{
  int i;

  assert(argc == 3);
  m_w = atoi(argv[1]);
  m_z = atoi(argv[2]);

  i = 10;
  while (i--);
    get_random();

  i = atoi(argv[2]);
  while (i--)
    printf("%d\n", (int) get_random() << 8 >> 22);

  return 0;
}

Примеры:

$ printf "1\n2\n-1\n4\n" | ./sum
6
$ printf "0\n-2\n-3\n" | ./sum
0

$ ./a.out 1 1 | ./sum
387
$ ./a.out 1 10 | ./sum
571
$ ./a.out 1 100 | ./sum
5867
$ ./a.out 1 1000 | ./sum
7531
$ ./a.out 1 10000 | ./sum
27268
$ ./a.out 1 100000 | ./sum
101332
$ ./a.out 1 1000000 | ./sum
187480
$ ./a.out 1 10000000 | ./sum
666307
  • ./sum мое решение
  • ./a.out это генератор

Ваше решение должно быть запущено в разумные сроки для всех тестов, описанных выше (мой тест выполняется за 1.2 с в последнем тестовом примере).

Самый короткий код выигрывает.

Изменить : Пожалуйста, приведите пример выполнения одного из тестов выше.


Вам нужно #include <stdlib.h>для atoi().
Пол Р

Мое собственное решение c заняло 4 секунды для последнего контрольного примера, очень заинтересованного в вашем решении.
Dongshengcn

Убедитесь, что вы сначала записываете в файл, а затем читаете из файла, а не используете каналы.
Александру

Я полагаю, в вашем генераторе есть ошибка, строка 25, while (i--);не должна заканчиваться точкой с запятой, не так ли?
неизвестный пользователь

assert (argc == 3) :-) Это то, что я называю удобной программой! :-)
Эмануэль Ландехольм,

Ответы:


3

Рубин, 53 персонажа

p$<.inject(-1.0/s=0){|a,b|[s=[0,s+b.to_i].max,a].max}

Занимает около 28 секунд для последнего теста здесь.


6

Python, 91 84 64 знака

s=m=0
try:
 while 1:s=max(s+input(),0);m=max(m,s)
except:print m

Занимает около 14 12 72 секунд в последнем тестовом случае. Изменить: с помощью алгоритма Пол Р. нашел. Редактировать: отменить импорт, используя input().


6

C, 100 символов


main(){char s[80];int i,m=0,n=0;while(gets(s)){i=atoi(s);n=n+i>0?n+i:0;m=m>n?m:n;}printf("%d\n",m);}


Время выполнения = 1,14 с для окончательного тестового примера (10000000) на 2,67 ГГц Core i7 с ICC 11.1 (ранее: 1,44 с с gcc 4.2.1).

Примечание. Алгоритм, использованный для вышеуказанного решения, взят из книги «Программирование жемчуга » Джона Бентли. По-видимому, этот алгоритм известен как алгоритм Кадане .


3

Хаскелл ( 88 64)

Реализация алгоритма Кадане.

main=interact$show.maximum.scanr(\x->max x.(x+))0.map read.lines

2

Питон - 114 символов

import sys
s=map(int,sys.stdin.readlines())
l=range(len(s)+1)
print`max(sum(s[i:j])for i in l[:-1]for j in l[i:])`

Это, конечно, не так быстро, как требуется, но работает нормально.


Это O (N ^ 2), которое, конечно, не соответствует требованиям задачи.
Александру

2

Python, использующий динамическое программирование - 92 символа

import sys
s=map(int,sys.stdin.readlines())
f=h=0
for x in s:h=max(0,h+x);f=max(f,h)
print f

2

J ( 34 33 символа)

Это решение реализует вариант алгоритма Кадане и является достаточно быстрым.

echo>./0,([>.+)/\.0".];._2(1!:1)3

Вот объяснение:

  • u/ y- Глагол u вставлен между элементами y. Например, +/ 1 2 3 4это как 1 + 2 + 3 + 4. Обратите внимание, что все глаголы в J ассоциированы справа, то -/ 1 2 3 4есть подобны 1 - (2 - (3 - 4))и вычисляют переменную сумму 1 2 3 4.
  • x >. y- максимум xа y.
  • x ([ >. +) y- Максимум xа x + y. [ >. +является глаголом в молчаливом обозначении и оценивается так же, как x >. x + y.
  • ([ >. +)/ y- непустой префикс yс наибольшей суммой.
  • u\. y- uприменяется ко всем суффиксам y. Обратите внимание, что специальный код обрабатывает общий случай так u/\. y, что он выполняется в линейном, а не в квадратичном времени.
  • ([ >. +)/\. y- Вектор, обозначающий самый большой непустой подмассив, который начинается в каждой позиции y.
  • 0 , ([ >. +)/\. y- подготовлен 0к предыдущему результату как 0длина пустого подмассива y.
  • >./ 0 , ([ >. +)/\. y- самый большой подмассив y.
  • 0 ". ];._2 (1!:1) 3 - Стандартный ввод маршалируется в вектор чисел.
  • >./ 0 , ([ >. +)/\. 0 ". ];._2 (1!:1) 3 - Самый большой подмассив в стандартном вводе.

1

Рубин, 68 символов

m=-2**31;n=0;$<.lines.map{|x|n+=x.to_i;n=0 if n<0;m=n if n>m};puts m

Также немного медленный, но завершает тесты 1-10000000 за полминуты, большую часть времени проведенную в последнем тесте ...

Версия с отступом:

m=-2**31
n=0
$<.lines.map {|x|
  n+=x.to_i
  n=0 if n<0
  m=n if n>m
}
puts m

1

C ++, 192 символа

#include <iostream>
#include <string>
#include <stdlib.h>
#define S std::
main(){long a=0,m=0,M=0;char s[9];while(S cin.getline(s,9)){a+=atoi(s);if(m>a)m=a;if(M<a-m)M=a-m;}S cout<<M<<S endl;}

Работает достаточно быстро на моем ноутбуке (4 секунды для последнего теста).


cstdlibнеstdlib.h
oldrinb

1
{if((r+$1)>0)
   r=r+$1 
 else r=0; 
 if(m<r) 
   m=r;
}
END{print m}

Код awk (66) , очень медленный, 8+ секунд для последнего теста

dwang@dwang-ws ~/Playground/lss $ time ./random 1 10000000 | awk -f lss.awk
666307

real    0m6.705s
user    0m8.671s
sys 0m0.052s
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.