Trova la più grande somma di sottosequenza


11

Data una sequenza di numeri interi, trova la somma più grande di una sottosequenza (numeri interi su posizioni consecutive) della sequenza. La sottosequenza può essere vuota (nel qual caso la somma è 0).

L'input viene letto dall'input standard, un numero intero per riga. La somma più grande deve essere scritta nell'output standard.

Ho scritto un piccolo generatore per te:

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

Esempi:

$ 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 è la mia soluzione
  • ./a.out è il generatore

La soluzione deve essere eseguita in tempi ragionevoli per tutti i test sopra indicati (la mia viene eseguita in 1,2 secondi sull'ultimo test case).

Il codice più corto vince.

Modifica : Fornisci un esempio eseguito su uno dei test sopra.


È necessario #include <stdlib.h>per atoi().
Paul R,

La mia soluzione c impiega 4 secondi per l'ultimo caso di test, molto interessato alla tua soluzione.
Dongshengcn,

Assicurati di scrivere prima in un file, quindi di leggere da un file e di non utilizzare pipe.
Alexandru,

Immagino che ci sia un errore nel tuo generatore, riga 25, while (i--);non dovrebbe finire in un punto e virgola, giusto?
utente sconosciuto

assert (argc == 3) :-) Questo è quello che chiamo un programma user friendly! :-)
Emanuel Landeholm,

Risposte:


3

Rubino, 53 caratteri

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

Ci vogliono circa 28 secondi per l'ultimo testcase qui.


6

Python, 91 84 64 caratteri

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

Dura circa 14 12 72 secondi sull'ultimo caso di test. Modifica: usando l'algoritmo Paul R trovato. Modifica: annullato l'importazione, usando input().


6

C, 100 caratteri


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


Tempo di esecuzione = 1,14 s per il caso di test finale (10000000) su Core i7 a 2,67 GHz con ICC 11,1 (in precedenza: 1,44 s con gcc 4.2.1).

Nota: l'algoritmo utilizzato per la soluzione di cui sopra proviene da Programming Pearls di Jon Bentley. Apparentemente questo algoritmo è noto come l'algoritmo di Kadane .


3

Haskell ( 88 64)

Implementazione dell'algoritmo di Kadane.

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

2

Python - 114 caratteri

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

Sicuramente non è veloce come richiesto, ma funziona bene.


Questo è O (N ^ 2) che certamente non soddisfa i requisiti della sfida.
Alexandru,

2

Python, usando la programmazione dinamica - 92 caratteri

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

Questa soluzione implementa una variante dell'algoritmo di Kadane ed è ragionevolmente veloce.

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

Ecco una spiegazione:

  • u/ y- Il verbo u inserito tra gli elementi di y. Ad esempio, +/ 1 2 3 4è come 1 + 2 + 3 + 4. Nota che tutti i verbi in J sono associati a destra, cioè -/ 1 2 3 4è simile 1 - (2 - (3 - 4))e calcola la somma alternata di 1 2 3 4.
  • x >. y- il massimo di xe y.
  • x ([ >. +) y- Il massimo di xe x + y. [ >. +è un verbo in notazione tacita e valuta come x >. x + y.
  • ([ >. +)/ y- il prefisso non vuoto di ycon la somma maggiore.
  • u\. y- uapplicato a tutti i suffissi di y. Si noti che il codice speciale gestisce il caso comune in modo u/\. yche questo venga eseguito in tempo lineare anziché quadratico.
  • ([ >. +)/\. y- Un vettore che indica il più grande sottoarray non vuoto che inizia in ciascuna posizione di y.
  • 0 , ([ >. +)/\. y- 0preceduto dal risultato precedente come 0è la lunghezza di un sottoarray vuoto di y.
  • >./ 0 , ([ >. +)/\. y- Il più grande subarray di y.
  • 0 ". ];._2 (1!:1) 3 - Input standard suddiviso in un vettore di numeri.
  • >./ 0 , ([ >. +)/\. 0 ". ];._2 (1!:1) 3 - Il più grande subarray nell'input standard.

1

Rubino, 68 caratteri

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

Anche un po 'lento, ma completa i test 1-10000000 in poco più di mezzo minuto, la maggior parte del tempo trascorso nell'ultimo test ...

Versione rientrata:

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 caratteri

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

Funziona abbastanza velocemente sul mio laptop (4 secondi per l'ultimo test).


cstdlibnostdlib.h
oldrinb,

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

awk Code (66) , molto lento, 8+ secondi per l'ultimo caso di test

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

real    0m6.705s
user    0m8.671s
sys 0m0.052s
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.