要求:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)
思路分析:
这个问题是一个典型的贪心算法的问题,限制于O(n)的时间复杂度,也就是只能用一次循环,所以一般的动态规划模型不经过优化很难完成。本题最关键的地方就是每次记录部分数组和时如何设置回溯、回溯到什么位置。这个题比较方便的地方在于数组中正负数都得有,也就是说得出的结果最差也得是个正数。好了,我们不妨设置一个用来记录部分数组和的sum值,初值为0,一个用来记录理想结果的max值,初值为数组中第一个元素的值a[0]。每次循环中,sum + a[i]都要和0比较大小,如果小等于0,说明当前这个部分和没有再记录的必要了,即时后面有很大的数能抵消也不是最理想的结果,这时就需要回溯,很简单,直接令sum = 0,从下次循环也就是下个位置重新记录即可;如果大于0,那么令sum = sum + a[i]这个好理解。再每次循环结束前,必须要记录当前的最理想结果,也就是把max和sum中较大的值赋值给max。
1 int main(){ 2 cout << "数字要求:必须有正数和负数同时存在,可以有0" << endl; 3 int len = 0; 4 cout << "输入数组长度:"; 5 cin >> len; 6 int*a = new int[len]; 7 cout << "输入" << len << "个数字:"; 8 for (int i = 0; i < len; ++i) 9 cin >> a[i]; 10 int sum = 0; 11 int max = a[0]; 12 for (int i = 0; i < len; ++i){ 13 if (sum + a[i] <= 0)sum = 0; 14 else sum += a[i]; 15 max = max>sum ? max : sum; 16 } 17 cout << "最大子数组的和:"<<max << endl; 18 return 0; 19 }
测试截图:
总结:
经典的贪心算法题目,主要就是回溯的位置和何时回溯。