Tìm tổng lớn nhất của chuỗi


11

Cho một dãy số nguyên tìm tổng lớn nhất của một dãy con (số nguyên trên các vị trí liên tiếp) của dãy. Phần tiếp theo có thể để trống (trong trường hợp đó tổng bằng 0).

Đầu vào được đọc từ đầu vào tiêu chuẩn, một số nguyên trên mỗi dòng. Số tiền lớn nhất phải được ghi vào đầu ra tiêu chuẩn.

Tôi đã viết một máy phát điện nhỏ cho bạn:

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

Ví dụ:

$ 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 là giải pháp của tôi
  • ./a.out là máy phát điện

Giải pháp của bạn phải chạy trong thời gian hợp lý cho tất cả các thử nghiệm ở trên (của tôi chạy trong 1,2 giây trong trường hợp thử nghiệm cuối cùng).

Mã ngắn nhất sẽ thắng.

Chỉnh sửa : Vui lòng cung cấp một ví dụ chạy trên một trong các bài kiểm tra ở trên.


Bạn cần #include <stdlib.h>cho atoi().
Paul R

Giải pháp c của riêng tôi mất 4 giây cho trường hợp thử nghiệm cuối cùng, rất quan tâm đến giải pháp của bạn.
Dongshengcn

Hãy chắc chắn rằng bạn viết đầu tiên vào một tệp và sau đó đọc từ tệp và không sử dụng các đường ống.
Alexandru

Tôi đoán có lỗi trong trình tạo của bạn, dòng 25, while (i--);không nên kết thúc bằng dấu chấm phẩy, phải không?
người dùng không xác định

khẳng định (argc == 3) :-) Đó là những gì tôi gọi là chương trình thân thiện với người dùng! :-)
Emanuel Landeholm 23/2/2015

Câu trả lời:


3

Ruby, 53 ký tự

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

Mất khoảng 28 giây cho lần thử nghiệm cuối cùng ở đây.


6

Python, 91 84 64 ký tự

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

Mất khoảng 14 12 72 giây trong trường hợp thử nghiệm cuối cùng. Chỉnh sửa: sử dụng thuật toán Paul R được tìm thấy. Chỉnh sửa: kết hợp nhập, sử dụng input().


6

C, 100 ký tự


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


Thời gian chạy = 1,14 giây cho trường hợp thử nghiệm cuối cùng (10000000) trên Core i7 2,67 GHz với ICC 11.1 (trước đây: 1,44 giây với gcc 4.2.1).

Lưu ý: Thuật toán được sử dụng cho giải pháp trên đến từ Lập trình Ngọc trai của Jon Bentley. Rõ ràng thuật toán này được gọi là Thuật toán Kadane .


3

Haskell ( 88 64)

Thực hiện thuật toán của Kadane.

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

2

Python - 114 ký tự

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

Nó chắc chắn không nhanh như yêu cầu, nhưng nó hoạt động tốt.


Đây là O (N ^ 2) chắc chắn không đáp ứng yêu cầu của thử thách.
Alexandru

2

Python, sử dụng lập trình động - 92 ký tự

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 ký tự)

Giải pháp này thực hiện một biến thể của thuật toán Kadane và nhanh chóng hợp lý.

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

Đây là một lời giải thích:

  • u/ y- Động từ u được chèn giữa các mục của y. Ví dụ, +/ 1 2 3 4là như thế 1 + 2 + 3 + 4. Lưu ý rằng tất cả các động từ trong J đều được liên kết đúng, nghĩa -/ 1 2 3 4là giống 1 - (2 - (3 - 4))và tính tổng của xen kẽ 1 2 3 4.
  • x >. y- mức tối đa của xy.
  • x ([ >. +) y- Tối đa xx + y. [ >. +là một động từ trong ký hiệu ngầm và đánh giá giống như x >. x + y.
  • ([ >. +)/ y- tiền tố không trống của yvới tổng lớn nhất.
  • u\. y- uáp dụng cho tất cả các hậu tố của y. Lưu ý rằng mã đặc biệt xử lý trường hợp phổ biến u/\. ysao cho mã này chạy theo tuyến tính thay vì thời gian bậc hai.
  • ([ >. +)/\. y- Một vectơ biểu thị phân đoạn không trống lớn nhất bắt đầu tại mỗi vị trí của y.
  • 0 , ([ >. +)/\. y- 0chuẩn bị trước kết quả trước đó 0là độ dài của một phân đoạn trống của y.
  • >./ 0 , ([ >. +)/\. y- Subarray lớn nhất của y.
  • 0 ". ];._2 (1!:1) 3 - Tiêu chuẩn đầu vào được sắp xếp thành một vectơ số.
  • >./ 0 , ([ >. +)/\. 0 ". ];._2 (1!:1) 3 - Subarray lớn nhất trong đầu vào tiêu chuẩn.

1

Ruby, 68 ký tự

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

Cũng hơi chậm, nhưng hoàn thành các thử nghiệm 1-10000000 trong hơn nửa phút, phần lớn thời gian dành cho thử nghiệm cuối cùng ...

Phiên bản thụt lề:

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 ký tự

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

Hoạt động khá nhanh trên máy tính xách tay của tôi (4 giây cho lần kiểm tra cuối cùng).


cstdlibkhôngstdlib.h
oldrinb

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

Mã awk (66) , rất chậm, hơn 8 giây cho trường hợp thử nghiệm cuối cùng

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

real    0m6.705s
user    0m8.671s
sys 0m0.052s
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.