剑指offer(三十)--连续子数组的最大和

Markdown在线编辑器 - www.MdEditor.com

题目

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

思路一

暴力搜索的话n+n-1+n-2+..+1 种
以第i做起始,往后延续了几个元素 ,时间复杂度(n*n) 空间复杂度(1)保存一个最大值
例如: 1 2 情况有三1;1 2;2;

思路二

这个典型的大问题换小问题(分治法递归或者动态规划)

先找递归式

递归式一

前n个元素连续子向量的最大和 = MAX(前n-1元素连续子向量最大和,以n结尾的所有情况)
如大问题 1 -2 10 ; 小问题 1 -2 小问题的解 最大值1 只取第一个元素;
根据小问题的状态,我们要搜索以10结尾的所有情况 (1 -2 10) (-2 10) (10);其结果和 小问题的解 1 去比较得到 最大为10(需要考虑n种情况)

递归式二

以第i+1个元素结尾的最大连续子向量的值 = MAX(以第i个元素结尾的最大连续子向量的值, 以第i个元素结尾的最大连续子向量的值+第i+1个元素的值)
最后得到n个值,然后去最大的,就是结果
如1 -2 10,小问题以-2 结尾的最大值 (1 -2)=-1 ,大问题以10为结尾的最大值比较(以10的上上一个元素结尾的最大值-1+10) (10);结果为10
(仅两种情况且不需要保存一个之前选取的那些元素的数组)

根据递归式写代码

class Solution {
public:
int Max(int a, int b) {
return a > b ? a :b ;
}
int FindGreatestSumOfSubArray(vector<int> array) {
int len = array.size();
if(len == 0) {
return 0;
}
int result[len] ; // 每个问题(以第i元素结尾的最大子向量)的解
result[0] = array[0];
for(int i = 1;i < len; i++) {
result[i] = Max(result[i-1] + array[i], array[i] );
}
int max = result[0];
for(int i= 1; i < len; i++) {
max = Max(max, result[i]);
}
return max;
}
};

 

End

posted @ 2020-01-15 17:13  碎梦残阳  阅读(98)  评论(0编辑  收藏  举报