找到最大的子序列总和


11

给定整数序列,可以找到该序列的子序列(在连续位置上的整数)的最大和。子序列可以为空(在这种情况下,总和为0)。

从标准输入读取输入,每行一个整数。必须将最大金额写入标准输出。

我为您编写了一个小型发电机:

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

例子:

$ 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.out 是发电机

对于上述所有测试,您的解决方案必须在合理的时间内运行(我的在最后一个测试用例中以1.2s运行)。

最短的代码获胜。

编辑:请提供一个在上述测试之一上运行的示例。


你需要#include <stdlib.h>atoi()
Paul R

我自己的c解决方案在最后一个测试用例上花了4秒钟,对您的解决方案非常感兴趣。
Dongshengcn

确保先写入文件,然后再从文件读取,并且不要使用管道。
亚历山德鲁

我猜您的生成器第25行有错误,while (i--);不应以分号结尾,应该吗?
用户未知

assert(argc == 3):-)这就是我所说的用户友好程序!:-)
伊曼纽尔·兰德霍尔姆

Answers:


3

Ruby,53个字符

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

最后一个用例大约需要28秒。


6

Python,91 84 64个字符

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

在最后一个测试用例上花费大约14 12 72秒。编辑:使用算法Paul R发现。编辑:使用取消了导入input()


6

C,100个字符


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


在带有ICC ​​11.1的2.67 GHz Core i7上,最终测试用例(10000000)的 运行时间= 1.14 s(以前:在gcc 4.2.1 上为1.44 s)。

注意:以上解决方案使用的算法来自Jon Bentley的Programming Pearls。显然,该算法被称为Kadane算法


3

哈斯克尔(88 64)

实现Kadane的算法。

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

2

Python-114个字符

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

它肯定没有达到要求的速度,但是可以正常工作。


这是O(N ^ 2),肯定不能满足挑战的要求。
亚历山德鲁

2

Python,使用动态编程-92个字符

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个字符)

该解决方案实现了Kadane算法的一种变体,并且速度很快。

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

这里是一个解释:

  • u/ y– 在的项目之间u 插入的动词y。例如,+/ 1 2 3 4就像1 + 2 + 3 + 4。请注意,以J所有动词右相关,即,-/ 1 2 3 4是像1 - (2 - (3 - 4))并计算的交替总和1 2 3 4
  • x >. y-最大的xy
  • x ([ >. +) y-最大xx + y[ >. +是隐含记号的动词,计算结果与相同x >. x + y
  • ([ >. +)/ yy总和最大的非空前缀。
  • u\. yu适用于的所有后缀y。请注意,特殊代码处理了常见情况u/\. y,因此它以线性而不是二次时间运行。
  • ([ >. +)/\. y–表示从的每个位置开始的最大非空子数组的向量y
  • 0 , ([ >. +)/\. y0优先于先前的结果,0是的空子数组的长度y
  • >./ 0 , ([ >. +)/\. y–的最大子数组y
  • 0 ". ];._2 (1!:1) 3 –将标准输入编组为数字向量。
  • >./ 0 , ([ >. +)/\. 0 ". ];._2 (1!:1) 3 –标准输入中最大的子数组。

1

Ruby,68个字符

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-10000000次测试,大部分时间都花在了上次测试上...

缩进版本:

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个字符

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

在我的笔记本电脑上运行得相当快(上次测试需要4秒)。


cstdlib不是stdlib.h
oldrinb 2012年

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

awk代码(66),非常慢,最后一个测试用例需要8+秒

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

real    0m6.705s
user    0m8.671s
sys 0m0.052s
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.