给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。
要求算法的时间复杂度为O(n)。
输入有两行:
第一行是n值(1<=n<=10000);
第二行是n个整数。
输出最大子段和。
思路描述:
从输入的整数序列的最后一位开始,从后往前,寻找最大的子段和,a[i+1]大于零,则让x[i]加上a[i+1];如果a[i+1]小于零,则将该值舍弃,因为倘若加上会使得a[i]变得比x[i]小,而我们是要求最大值。
代码主体:
#include <iostream>
#include<algorithm>
using namespace std;
int main(int argc, char** argv) {
int n, max;
int x[1000];
int a[1000];
max = 0;
cin >> n;
a[n] = x[n];//初始化a[n]的值为输入的最后一个序列
for(int i = 1; i <= n; i++)
{
cin >> x[i];
}
for(int i = n - 1; i >= 1; i--)
{
if(a [i+1]> 0)//如果后面的子段序列和大于零,则让a[i] = x[i]+a[i+1]
{
a[i] = x[i]+a[i+1];
}
else//如果后面的子段序列和大于等于零,则直接舍弃
{
a[i] = x[i];
}
max = max(a);//最大子段和
cout << max;
return 0;
}
a [i+1]+x[i] , a[i+1] > 0
a[i] =
x[i], a[i+1] <= 0
一个一维表格;填表范围从1到n;从n开始往前填,填到1
时间复杂度:O(n)
只遍历了一次数组
空间复杂度:O(n)
只利用了两个数组a和x进行数据的记录
收获:对于一些问题,从前往后填表或者从后往前填表都可行。有时也可根据所需的数据判断运用填表思想时是否需要创建表格记录数据,还是只需设置变量记录后续用到的数据而舍弃其它无用的数据。填表问题只需按照步骤走就能解决,分析最优解的性质,并刻画其结构特征,递归的定义最优解,构造递归式子,以自底向上或自顶向下的方式构造问题的最优解
动态规划算法通常基于一个递推公式及一个或多个初始状态。当前子问题的解将由上一次子问题的解推出。动态规划的核心思想是把原问题分解成子问题进行求解,也就是分治的思想。动态规划算法只需要求出构造递归式子,并根据式子填表就能解决,使问题变得更为简明,降低复杂度,使得解题思路更加清晰。