Encontre a maior soma de subsequência

11

Dada uma sequência de números inteiros, encontre a maior soma de uma subsequência (números inteiros em posições consecutivas) da sequência. A subsequência pode estar vazia (nesse caso, a soma é 0).

A entrada é lida a partir da entrada padrão, um número inteiro por linha. A maior soma deve ser gravada na saída padrão.

Eu escrevi um pequeno gerador para você:

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

Exemplos:

$ 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 minha solução
  • ./a.out é o gerador

Sua solução deve ser executada em tempo razoável para todos os testes acima (o meu é executado em 1,2s no último caso de teste).

O menor código vence.

Editar : forneça um exemplo executado em um dos testes acima.

Alexandru
fonte
Você precisa #include <stdlib.h>para atoi().
Paul R
Minha própria solução c leva 4 segundos para o último caso de teste, muito interessada em sua solução.
Dongshengcn
Certifique-se de escrever primeiro em um arquivo e depois ler o arquivo, e não usar pipes.
Alexandru
Acho que há um erro no seu gerador, linha 25, while (i--);não deve terminar em ponto e vírgula, não é?
usuário desconhecido
assert (argc == 3) :-) É o que eu chamo de um programa amigável! :-)
Emanuel Landeholm

Respostas:

3

Ruby, 53 caracteres

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

Leva cerca de 28 segundos para o último caso de teste aqui.

Ventero
fonte
6

Python, 91 84 64 caracteres

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

Leva cerca de 14 12 72 segundos no último caso de teste. Edit: usando o algoritmo que Paul R encontrou. Editar: nixou a importação, usando input().

boothby
fonte
6

C, 100 caracteres


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 de execução = 1,14 s para o caso de teste final (10000000) no Core i7 de 2,67 GHz com ICC 11.1 (anteriormente: 1,44 s com gcc 4.2.1).

Nota: O algoritmo usado para a solução acima vem de Programming Pearls, de Jon Bentley. Aparentemente, esse algoritmo é conhecido como algoritmo de Kadane .

Paul R
fonte
3

Haskell ( 88 64)

Implementando o algoritmo de Kadane.

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

Python - 114 caracteres

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

Certamente não é tão rápido quanto necessário, mas funciona bem.

Juan
fonte
Este é O (N ^ 2) que certamente não atende aos requisitos do desafio.
Alexandru
2

Python, usando programação dinâmica - 92 caracteres

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
BioGeek
fonte
2

J ( 34 33 caracteres)

Esta solução implementa uma variante do algoritmo de Kadane e é razoavelmente rápida.

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

Aqui está uma explicação:

  • u/ y- O verbo u inserido entre os itens de y. Por exemplo, +/ 1 2 3 4é como 1 + 2 + 3 + 4. Observe que todos os verbos em J estão associados à direita, ou seja, -/ 1 2 3 4são semelhantes 1 - (2 - (3 - 4))e calculam a soma alternada de 1 2 3 4.
  • x >. y- o máximo de xe y.
  • x ([ >. +) y- O máximo de xe x + y. [ >. +é um verbo em notação tácita e é avaliado da mesma forma que x >. x + y.
  • ([ >. +)/ y- o prefixo não vazio de ycom a maior soma.
  • u\. y- uaplicado a todos os sufixos de y. Observe que o código especial lida com o caso comum, de u/\. ymodo que seja executado em tempo linear e não quadrático.
  • ([ >. +)/\. y- Um vetor que denota o maior subarray não vazio que inicia em cada posição de y.
  • 0 , ([ >. +)/\. y- 0pré-previsto para o resultado anterior, assim como 0o comprimento de um subarray vazio de y.
  • >./ 0 , ([ >. +)/\. y- O maior sub-arranjo de y.
  • 0 ". ];._2 (1!:1) 3 - Entrada padrão empacotada em um vetor de números.
  • >./ 0 , ([ >. +)/\. 0 ". ];._2 (1!:1) 3 - O maior subarray da entrada padrão.
FUZxxl
fonte
1

Ruby, 68 caracteres

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

Também um pouco lento, mas conclui os testes 1-10000000 em pouco mais de meio minuto, a maior parte do tempo gasto no último teste ...

Versão recuada:

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

C ++, 192 caracteres

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

Funciona razoavelmente rápido no meu laptop (4 segundos para o último teste).

Benoit
fonte
cstdlibnãostdlib.h
oldrinb
1
{if((r+$1)>0)
   r=r+$1 
 else r=0; 
 if(m<r) 
   m=r;
}
END{print m}

Código awk (66) , muito lento, mais de 8 segundos para o último caso de teste

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

real    0m6.705s
user    0m8.671s
sys 0m0.052s
Dongshengcn
fonte