En büyük alt sekansı bulun


11

Bir tamsayı dizisi verildiğinde, dizinin bir alt dizisinin (ardışık konumlardaki tamsayılar) en büyük toplamını bulur. Sonraki dizi boş olabilir (bu durumda toplam 0'dır).

Giriş, her satır için bir tamsayı olan standart girişten okunur. En büyük toplam standart çıktıya yazılmalıdır.

Senin için küçük bir jeneratör yazdım:

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

Örnekler:

$ 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 benim çözümüm
  • ./a.out jeneratör

Çözümünüz yukarıdaki tüm testler için makul sürede çalışmalıdır (benimki son test durumunda 1.2 saniye içinde çalışır).

En kısa kod kazanır.

Düzenleme : Lütfen yukarıdaki testlerden birinde bir örnek çalıştırma sağlayın.


İhtiyacınız #include <stdlib.h>için atoi().
Paul R

Kendi c çözümüm, son test vakası için 4 saniye sürüyor, çözümünüzle çok ilgileniyor.
Dongshengcn

Önce bir dosyaya yazıp dosyadan okuduğunuzdan ve kanal kullanmamaya dikkat edin.
Alexandru

Sanırım jeneratörde bir hata var, hat 25, while (i--);noktalı virgülle bitmemeli, değil mi?
kullanıcı bilinmiyor

assert (argc == 3) :-) Buna kullanıcı dostu bir program diyorum! :-)
Emanuel Landeholm

Yanıtlar:


3

Ruby, 53 karakter

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

Buradaki son testcase için yaklaşık 28 saniye sürüyor.


6

Python, 91 84 64 karakter

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

Son test vakasında yaklaşık 14 12 72 saniye sürer. Düzenleme: Paul R algoritması kullanarak bulundu. Düzenleme: kullanarak içe aktarma işlemini karıştırdı input().


6

C, 100 karakter


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


Çalışma süresi = ICC 11.1 ile 2.67 GHz Core i7'de son test durumu (10000000) için 1.14 s (önceden: gcc 4.2.1 ile 1.44 s ).

Not: Yukarıdaki çözüm için kullanılan algoritma Jon Bentley tarafından Programlama İncilerinden gelir . Görünüşe göre bu algoritma Kadane Algoritması olarak biliniyor .


3

Haskell ( 88 64)

Kadane algoritmasını uygulamak.

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

2

Python - 114 karakter

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

Elbette gerektiği kadar hızlı değil, ama iyi çalışıyor.


Bu kesinlikle meydan okuma şartlarını karşılamayan O (N ^ 2).
Alexandru

2

Python, dinamik programlama kullanarak - 92 karakter

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

Bu çözüm, Kadane algoritmasının bir varyantını uygular ve makul hızlıdır.

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

İşte bir açıklama:

  • u/ y- öğelerinin u arasına eklenen fiil y. Örneğin, +/ 1 2 3 4benzer 1 + 2 + 3 + 4. J tüm fiiller sağ ilişkili olduğunu Bildirimi olduğunu, -/ 1 2 3 4gibi1 - (2 - (3 - 4)) alternatif toplamına ve hesapladığına dikkat edin 1 2 3 4.
  • x >. y- maksimum xvey .
  • x ([ >. +) y- Maksimum xve x + y. [ >. +zımni gösterimde bir fiildir ve şu şekilde değerlendirilir:x >. x + y .
  • ([ >. +)/ y - boş olmayan öneki y büyük toplamın .
  • u\. y- uöğesinin tüm eklerine uygulanır y. Özel kodun genel durumu ele aldığına dikkat edinu/\. y ikinci dereceden zaman yerine doğrusal olarak çalışacak şekilde .
  • ([ >. +)/\. y - Her konumunda başlayan en büyük boş olmayan alt diziyi gösteren bir vektör y .
  • 0 , ([ >. +)/\. y- boş bir alt dizinin uzunluğu 0gibi önceki sonuca önceden eklenmiş0y .
  • >./ 0 , ([ >. +)/\. y - En büyük alt dizisi y .
  • 0 ". ];._2 (1!:1) 3 - Standart girdi bir sayı vektörüne eklenir.
  • >./ 0 , ([ >. +)/\. 0 ". ];._2 (1!:1) 3 - Standart girişteki en büyük alt dizi.

1

Yakut, 68 karakter

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

Ayrıca biraz yavaş, ancak 1-10000000 testlerini yarım dakikadan biraz fazla bir sürede tamamlar, çoğu zaman son testte harcanır ...

Girintili sürüm:

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 karakter

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

Dizüstü bilgisayarımda oldukça hızlı çalışıyor (son test için 4 saniye).


cstdlibdeğilstdlib.h
oldrinb

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

awk Code (66) , çok yavaş, son test senaryosu için 8+ saniye

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

real    0m6.705s
user    0m8.671s
sys 0m0.052s
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.