一、实践题目
7-2 最大子段和
二、问题描述
要求编写一个时间复杂度为O(n)的算法,去求解给定n个整数(包含负数)组成的序列a[1],a[2],a[3],…,a[n]中的子段和的最大值,规定当所给的整数均为负数时,定义子段和为0。
三、算法描述
定义一个辅助数组note[n],note[i]记录序列a[1],a[2],a[3],…,a[i]中以a[i]结尾的子段和的最大值,note[i]初始化为a[i]。从a[2]开始,一直到a[n],更新note[i]的值,若note[i - 1]大于0,note[i]的值变为note[i - 1] + note[i]。循环结束后,由1至n, 找出note[i]的最大值,即为所求问题的解。
具体代码如下:
1 #include <iostream> 2 using namespace std; 3 4 int main() { 5 int n; 6 cin >> n; 7 int a[n]; 8 int note[n]; 9 for (int i = 0; i < n; i++) { 10 cin >> a[i]; 11 note[i] = a[i]; 12 } 13 for (int i = 1; i < n; i++) 14 note[i] = note[i - 1] > 0 ? note[i - 1] + note[i] : note[i]; 15 int max = note[0]; 16 for (int i = 1; i < n; i++) 17 if (note[i] > max) 18 max = note[i]; 19 if (max < 0) 20 max = 0; 21 cout << max << endl; 22 return 0; 23 }
四、算法时间及空间复杂度分析
算法时间复杂度:
该算法更新note[i]时,包含一个1~n的for循环(内部为判断条件,更新note[i],为常数级操作),查找最大值时,也包含一个1~n的for循环,故该算法时间复杂度为O(n)。
算法空间复杂度:
该算法使用了一个一维数组note[n],note[i]记录序列a[1],a[2],a[3],…,a[i]中以a[i]结尾的子段和的最大值。故该算法空间复杂度为O(n)。若是不需要读取输入序列,则可进一步优化该算法的空间复杂度,直接在a[n]的基础上进行操作,该算法空间复杂度将变为O(1)。
五、心得体会
本次为我和搭档的第二次上机实验,该题采用的是动态规划,算是动态规划中较为简单的一道。在编写本题时,我们先是各自思考思路,双方都想清楚之后交流想法,巧合的是我们的思路完全一致。