算法第二章上机实践报告
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 maxsum(int a[], int l, int r) { if (l == r) { return 0; } int m = (l + r) / 2; //cout<<l<<" "<<r<<" "<<m<<endl; int lmax = maxsum(a, l, m ); int rmax = maxsum(a, m+1, r); int lsum = 0, rsum = 0, lsummax = 0, rsummax = 0; for (int i = m ; i >= l; i--) { lsum += a[i]; if (lsum > lsummax) lsummax = lsum; } for (int j = m+1; j <= r; j++) { rsum += a[j]; if (rsum > rsummax) rsummax = rsum; } int crosssummax = lsummax + rsummax; int max = lsummax > rsummax ? lsummax : rsummax; max = max > crosssummax ? max : crosssummax; return max; } int main() { int num[100000]; int n; cin >> n; for (int i = 0; i < n; i++) { cin >> num[i]; } int max = maxsum(num, 0, n - 1); cout << max; return 0; }
4、算法时间及空间复杂度分析
时间复杂度分析:
1)分解子问题:将原序列一分为二,时间复杂度为O(1)
2)求解子问题:子问题的规模,是原来问题规模的一半;原问题分解为两个相同的子问题。所以时间复杂度为2T(n/2)
3)合并子问题的解:每一次递归调用,就合并一次子问题的解。一共需要递归调用n/2次,所以时间复杂度为O(n)
T(n) = O(nlogn)
空间复杂度分析:
空间复杂度为O(n),用于存储输入数据
5、心得体会
通过这道题,学会了分治法的一个实例运用,对分治法有了更深的体会。
编程的过程中也有遇到比较低级的错误,就是跟伪码搞混,这两行的函数调用中,参数范围刚开始写错了。
int lmax = maxsum(a, l, m );
int rmax = maxsum(a, m+1, r);
int max = maxsum(num, 0, n - 1);