Знайдіть найбільшу суму підрядності


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().
Пол Р.

Моє власне рішення займає 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

Пітона, 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).

Примітка: Алгоритм , який використовується для зазначеного вище рішення походить від програмування Pearls Джона Бентлі. Мабуть, цей алгоритм відомий як Алгоритм Кадана .


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.