算法第二章上机实践报告
1.实践题目:最大子列和问题
2.问题描述:给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
3.算法描述:首先用递归判断,再将子列平分为两段,求左序列最大子段、右序列最大子段和和中间序列最大子段和。最后通过比较得出该子列的最大子段和。代码如下
#include<iostream>
using namespace std;
int Max(int leftmaxsum, int rightmaxsum, int maxbordersum){
int tempmax=leftmaxsum;
if(rightmaxsum>tempmax){
tempmax=rightmaxsum;
}
if(maxbordersum>tempmax){
tempmax=maxbordersum;
}
return tempmax;
}
int Maxsum(int *a, int left, int right){
if(left==right){
if(a[left]>0){
return a[left];
}
else return 0;
}
int mid=(left+right)/2;
int leftmaxsum=Maxsum(a, left, mid);//左序列最大字段和
int rightmaxsum=Maxsum(a, mid+1, right);//右序列最大字段和
//中间序列最大字段和
int maxleftbordersum=0;
int maxrightbordersum=0;
int tempsum1=0, tempsum2=0;
for(int i=mid;i>=left;i--){
tempsum1 += a[i];
if(tempsum1>maxleftbordersum){
maxleftbordersum=tempsum1;
}
}
for(int i=mid+1;i<=right;i++){
tempsum2 += a[i];
if(tempsum2>maxrightbordersum){
maxrightbordersum=tempsum2;
}
}
return Max(leftmaxsum, rightmaxsum, maxleftbordersum+maxrightbordersum);
}
int main(){
int a[100000];
int n;
cin>>n;
int left=0, right=n-1, max=0;
for(int i=0;i<n;i++){
cin>>a[i];
}
max=Maxsum(a, left, right);
cout<<max;
return 0;
}
4.算法时间及空间复杂度分析:每次将子段分为两段递归,共logn层,每层处理横跨左右的子段和,故时间复杂度为O(nlogn)
空间复杂度为O(n),用于存储输入数据
5.心得体会:本次实践了解了分治法的基本思想,即将一个规模较大的问题分解为几个规模较小的问题,将这些子问题递归解决后再合并得到原问题解。