问题的输入是具有n个浮点数的向量x,输出是输入向量的任何连续子向量中的最大和。,例如,如果输入向量包含下面10个元素:
31,-41,59,26,-53,58,97,-93,-23,84
那么该程序的输出为x[2..6]的总和,即187。当所有的数都是正数时,问题就很容易解决,此时最大子向量就是整个输入向量。当输入向量中有负数时就有麻烦了:是否应该包含某个负数时希望周围的正数会弥补它呢?为了使问题的定义更加完整,我们认为当所有的输入都是负数时,总和最大的子向量是空向量,总和为0。
完成该任务的浅显程序对所有满足0<=i<=j<n的(i,j)整数对进行迭代。对每个整数对,程序都要计算x[i..j]的总和,并检验该总和是否大于迄今为止的最大总和。算法1的伪代码如下所示:
maxsofar = 0
for i = [0,n)
for j = [i,n)
sum = 0
for k = [i,j]
sum += x[k]
maxsofar = max(maxsofar, sum)
这段代码简洁易懂,但不幸的是,程序的运行速度很慢。
大多数的人可能立刻就能看出可以更简洁方法,如下面两个:
可以注意到,x[i..j]的总和与前面已经计算出的总和(x[i..j-1]的总和)密切相关,利用这一关系即可得到算法2:
maxsofar = 0
for i = [0,n)
sum = 0
for j = [i,n)
sum += x[k]
<span> </span>maxsofar = max(maxsofar, sum)
第一个循环内的语句需要执行n次,第二个循环内的语句在每次执行外循环时至多执行n次,所以总的运行时间是O(n^2)。
另一个平方算法是通过访问在外循环执行之前就已构建的数据结构的方式在内循环中计算总和。cumarr中的第i个元素包含x[0..i]中的各个数的累加和,所以x[i..j]中的各个数的总和可以通过计算cumarr[j] - cumarr[i-1]得到。从而我们可以得到算法2b的代码,如下所示:
cumarr[-1] = 0
for i = [0, n)
cumarr[i] = cumarr[i - 1] + x[i]
maxsofar = 0
for i = [0, n)
for j = [i, n)
sum = cumarr[j] - cumarr[i-1]
maxsofar = max(maxsofar, sum)
maxsofar = 0
maxendinghere = 0
for i = [0,n)
maxendinghere = max(maxendinghere + x[i], 0)
maxsofar = max(maxsofar, maxendinghere)
该算法的运行时间为O(n),因此我们称之为线性算法。