谈最大子段和问题的三种解题策略

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

最大子段和问题的不同策略分析与实现
最大子段和问题描述:给定由N 个整数(可能为负整数)组成的序列a 1,a 2,…,a n ,求该序列形如∑=j
i k k a 的子段和的最大值。

当所有整数均为负整数时定义其最大子段
和为0。

例如当(a 1,a 2,…,a 6)=(-2,11,-4,13,-5,-2)时最大子段和为20,即a 2,a 3,a 4序列为最大子段。

下面我们来探讨一下解决这个问题的三种不同策略。

一、枚举策略
这种策略是我们最容易想到的,依照最大子段和的定义,不难理解所求最大子段和为max{0,max ∑=j
i k k a (其中1≤i ≤j ≤n)},所以我们只需枚举所有的i 和j 即可求出序列
的最大的子段和。

主要代码如下,其中a[i]表示a i 。

procedure maxsum(V AR max :longint);
var
i,j :integer;
thissum :longint;
begin
max :=0;
for i :=1 to n do
begin
thissum :=0;
for j :=i to n do
begin
thissum :=thissum+a[j];
if max<thissum then max :=thissum;
end;
end;
end;
此算法的时间复杂度为O(n 2)。

二、分治策略
针对最大子段和这个具体问题本身结构,我们还能够从算法设计策略上对上述算法实行改进。

从问题解的结构能够看出,它适合于分治算法求解。

如果将所给的序列a 1,a 2,…,a n 分为长度相等的两段序列a 1,a 2,…,a (n div 2) 和a (n div 2+1),a (n div 2+2),…,a n ,分别求出这两段的最大子段和,则a 1,a 2,…,a n 的最大子段和有三种可能:
1.a 1,a 2,…,a n 的最大子段在前半段,即序列a 1,a 2,…,a n 的最大子段和与a 1,a 2,…,a (n div 2) 序列的最大子段和相等。

2.a 1,a 2,…,a n 的最大子段在后半段,即序列a 1,a 2,…,a n 的最大子段和与a (n div 2+1),a (n div 2+2),…,a n 序列的最大子段和相等。

3.a1,a2,…,a n的最大子段的段首元素在前半段,段尾元素在后半段,即a(n div 2)和a(n div 2+1)都在最大子段内。

对于第一和第二种情形,我们能够由递归求得,对于第三种情形,我们能够先在前半段求出以a(n div 2)为尾的最大子段和S1,再在后半段求出以a(n div 2+1)为首的最大子段和S2,则S1+S2即为第三种情形的最大子段和。

主要代码如下,其中a[i]表示a i。

procedure maxsum(x,y:integer;var max:longint);
var
center,i:integer;
s1,s2,lefts,rights,leftmax,rightmax:longint;
begin
if x=y then begin
if a[x]<0 then max:=0
else max:=a[x];
end
else begin
center:=(x+y) div 2;
maxsum(x,center,leftmax);
maxsum(center+1,y,rightmax);
s1:=0;
lefts:=0;
for i:=center downto x do
begin
lefts:=lefts+a[i];
if s1<lefts then s1:=lefts;
end;
s2:=0;
rights:=0;
for i:=center+1 to y do
begin
rights:=rights+a[i];
if s2<rights then s2:=rights;
end;
max:=s1+s2;
if max<leftmax then max:=leftmax;
if max<rightmax then max:=rightmax;
end;
end;
此种算法的时间复杂度为O(nlogn)。

三、动态规划策略
设b[j]表示以a j为尾的最大子段和,显然有当b[j-1]>0时,b[j]=b[j-1]+a[j],否则b[j]=a[j],明显具有最优子结构和无后效性,适宜用动态规划来解决。

由此可得状态转移方程:b[j]=max{b[j-1]+a[j],a[j]},临界状态:如果a[1]≥0,b[1]=a[1],否则b[1]=0,
最终所求就是。

主要代码如下,其中a[i]表示a i。

procedure maxsum(var max:longint);
var
b:array[1..30000] of longint;
i:integer;
beg
if a[1]<0 then b[1]:=0
else b[1]:=a[1];
max:=b[1];
for i:=2 to n do
begin
if b[i-1]>=0 then b[i]:=b[i-1]+a[i]
else b[i]:=a[i];
if max<b[i] then max:=b[i];
end;
end;
此算法的时间复杂度为O(n)。

同一个问题,采用了不同的策略,得到了不同的执行效率。

这就要求我们在平时的训练中,鼓励和引导学生从不同的角度或策略去分析解决问题,从而提升学生分析问题和解决问题水平。

相关文档
最新文档