算法第三章实践报告
1.1 题目描述
给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。
要求算法的时间复杂度为O(n)。
输入格式:
输入有两行:
第一行是n值(1<=n<=10000);
第二行是n个整数。
输出格式:
输出最大子段和。
输入样例:
在这里给出一组输入。例如:
6
-2 11 -4 13 -5 -2
输出样例:
在这里给出相应的输出。例如:
20
用s[]数组来储存最大字段和,a[]储存输入数组。若s[i-1]小于0,则舍弃前面的和,从a[i]重新开始加和;否则继续将a[i]累加到s[i-1]上,s[i]=s[i-1]+a[i]。
#include<iostream>
using namespace std;
int main()
{
int n,a[100000],s[100000];
int max=-1;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
int flag=0;
s[1]=a[1];
for(int i=1;i<=n;i++)
{
if(a[i]<0) flag++;
}
if(flag=n) max=0;
for(int i=2;i<=n;i++)
{
if(s[i-1]<0) s[i]=a[i];
else s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
if(s[i]>max) max=s[i];
}
cout<<max;
return 0;
}
1.3.1 递归方程式
if(s[i-1]<0) s[i]=a[i];
else s[i]=s[i-1]+a[i];
1.3.2 填表法中表的维度、填表范围和填表顺序
1*n的表格,从s[1]填到s[n]
1.3.3 分析该算法的时间和空间复杂度
for(int i=2;i<=n;i++)
{
if(s[i-1]<0) s[i]=a[i];
else s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
if(s[i]>max) max=s[i];
}
仅进行了一次n-1次和一次n次的循环,所以时间复杂度为O(n)
空间复杂度为O(n)
1.4心得体会
动态规划问题往往是求最大或最小即最优解的问题,用整形变量max或其他变量名代替数组作最后的输出,在面临一些特殊情况后者临界条件时会比较好操作。
2. 你对动态规划算法的理解和体会
动态规划法就是通过递归思想外加变量来储存已经计算过的结果,再在后面将这些结果重新利用起来,减少大量的重复运算。