Znajdź największą sumę podsekwencji


11

Biorąc pod uwagę sekwencję liczb całkowitych, znajdź największą sumę podsekwencji (liczby całkowite na kolejnych pozycjach) sekwencji. Podsekwencja może być pusta (w takim przypadku suma wynosi 0).

Wejście jest odczytywane ze standardowego wejścia, jedna liczba całkowita na linię. Największa suma musi być zapisana na standardowe wyjście.

Napisałem dla ciebie mały generator:

#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;
}

Przykłady:

$ 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 to moje rozwiązanie
  • ./a.out jest generatorem

Twoje rozwiązanie musi zostać uruchomione w rozsądnym czasie dla wszystkich powyższych testów (moje działa w 1,2 sekundy w ostatnim przypadku testowym).

Najkrótszy kod wygrywa.

Edycja : Podaj przykładowy przebieg jednego z powyższych testów.


Trzeba #include <stdlib.h>za atoi().
Paul R

Moje własne rozwiązanie C zajmuje 4 sekundy dla ostatniego przypadku testowego, bardzo zainteresowany twoim rozwiązaniem.
Dongshengcn

Upewnij się, że najpierw piszesz do pliku, a następnie czytasz z pliku, a nie używasz potoków.
Alexandru

Chyba w twoim generatorze jest błąd, wiersz 25, while (i--);nie powinien kończyć się średnikiem, prawda?
użytkownik nieznany

assert (argc == 3) :-) Tak nazywam program przyjazny dla użytkownika! :-)
Emanuel Landeholm

Odpowiedzi:


3

Ruby, 53 znaki

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

Ostatni test testowy zajmuje około 28 sekund.


6

Python, 91 84 64 znaków

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

Ostatni test trwa około 14 12 72 sekund. Edycja: za pomocą algorytmu znaleziono Paul R. Edycja: nixed import, używając input().


6

C, 100 znaków


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);}


Czas pracy = 1,14 s dla końcowego przypadku testowego (10000000) na 2,67 GHz Core i7 z ICC 11.1 (wcześniej: 1,44 s z gcc 4.2.1).

Uwaga: Algorytm zastosowany w powyższym rozwiązaniu pochodzi z Programming Pearls autorstwa Jona Bentleya. Najwyraźniej ten algorytm jest znany jako Algorytm Kadane'a .


3

Haskell ( 88 64)

Implementacja algorytmu Kadane.

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

2

Python - 114 znaków

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:])`

Z pewnością nie jest tak szybki, jak to wymagane, ale działa dobrze.


To jest O (N ^ 2), które z pewnością nie spełnia wymagań wyzwania.
Alexandru

2

Python, wykorzystujący programowanie dynamiczne - 92 znaki

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 znaki)

To rozwiązanie implementuje wariant algorytmu Kadane i jest dość szybkie.

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

Oto wyjaśnienie:

  • u/ y- Czasownik u wstawiony między pozycje y. Np. +/ 1 2 3 4Jest jak 1 + 2 + 3 + 4. Zauważ, że wszystkie czasowniki w J są powiązane z prawą, to znaczy -/ 1 2 3 4są podobne 1 - (2 - (3 - 4))i obliczają przemienną sumę 1 2 3 4.
  • x >. y- maksimum xi y.
  • x ([ >. +) y- maksimum xi x + y. [ >. +jest czasownikiem w milczącej notacji i działa tak samo jak x >. x + y.
  • ([ >. +)/ y- niepusty prefiks yz największą sumą.
  • u\. y- uzastosowane do wszystkich przyrostków y. Zauważ, że specjalny kod obsługuje zwykły przypadek u/\. y, który działa liniowo zamiast kwadratowo.
  • ([ >. +)/\. y- Wektor oznaczający największą niepustą podtablicę, która zaczyna się w każdej pozycji y.
  • 0 , ([ >. +)/\. y- 0wstępnie przygotowany do poprzedniego wyniku, podobnie jak 0długość pustej podtablicy o wartości y.
  • >./ 0 , ([ >. +)/\. y- Największa podtablica y.
  • 0 ". ];._2 (1!:1) 3 - Standardowe wejście zestawione w wektor liczb.
  • >./ 0 , ([ >. +)/\. 0 ". ];._2 (1!:1) 3 - Największa podtablica na standardowym wejściu.

1

Ruby, 68 znaków

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

Również trochę powolny, ale wykonuje testy 1-10000000 w nieco ponad pół minuty, większość czasu spędzonego na ostatnim teście ...

Wersja wcięta:

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 znaki

#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;}

Działa dość szybko na moim laptopie (4 sekundy do ostatniego testu).


cstdlibniestdlib.h
oldrinb,

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

kod awk (66) , bardzo wolny, ponad 8 sekund dla ostatniego przypadku testowego

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

real    0m6.705s
user    0m8.671s
sys 0m0.052s
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.