问题:求连续子数组的最大和
算法1:
首先用一个变量maxSum来保存最大和。
从数组的第一元素开始,遍历整个数组。并用currSum来保存遍历过程中最大子数组的和。
在遍历每个元素的时候:
1、首先,将这个元素和最大和maxSum比较,如果大于maxSum,就将这个元素赋给maxSum。
2、同时,判断当前子数组的和currSum是否大于0。如果currSum大于0,将这个元素的值和currSum相加。否则,将当前元素的值直接赋给currSum。(为什么?我是这么考虑的,如果遍历到第i个元素,第i个元素之前的子数组的和currSum,且currSum的值为负,那么如果currSum和第一个元素相加,不论第i个元素为什么,最终的和与第i个元素相比较,只会更小。所以说,如果currSum为负,currSum只会使削弱后面子数组的和,所以舍弃这个负的值)
3、比较currSum和maxSum,如果maxSum小于currSum,就把currSum赋值给maxSum
代码如下:
class Solution {
public:
//求解问题代码开始
int FindGreatestSumOfSubArray(vector<int> array) {//
if (array.size() == 0){
//throw new exception();
return 0;
}
int maxSum = 0x80000000;
int currSum = 0x80000000;
for (vector<int>::iterator ite = array.begin(); ite != array.end(); ite++){
if (*ite > maxSum){
maxSum = *ite;
}
if (currSum < 0){
currSum = *ite;
}
else {
currSum += *ite;
}
if (currSum > maxSum){
maxSum = currSum;
}
}
return maxSum;
}
};
上面算法的优点是,多项式时间内即可完成比较。缺点是,没有给出哪段元素的和最大。
当然,也可采用分治算法求解这道题目。
算法2:采用分治法:
1、将一个数组分为两部分,左半部分和有半部分;分别求这两部分的最大子数组的和(递归)。
2、整个数组的最大子数组和也可能是跨越这两部分数组,因此还得求跨越左右两部分子数组的最大子数组和
3、最后比较这三部分,并返回最大值。
class Solution {
public:
int FindGreatestSumOfSubArray(vector<int> array) {
//
if (array.size() == 0){
//throw new exception();
return 0;
}
int maxSum = 0x80000000;
maxSum = FindGreatSumOfSubArray(array, 0, array.size() - 1);
return maxSum;
}
int FindGreatSumOfSubArray(vector<int> &array, int begin, int end){
if (begin == end){
return array[begin];
}
int max = 0;
int mid = (begin + end) / 2;.//使用mid将数组分为两部分
int leftMax = FindGreatSumOfSubArray(array, begin, mid);//求左半部分最大和
int rightMax = FindGreatSumOfSubArray(array, mid + 1, end);//求有半部分最大和
//接下来求跨越左半部分和有半部分的最大和
int midtoLeftMax = 0x80000000;
int midtoRightMax = 0x80000000;
int midMax;
for (int i = mid, currSum = 0; i >= begin; i--){
currSum += array[i];
if (currSum > midtoLeftMax){
midtoLeftMax = currSum;
}
}
for (int i = mid + 1, currSum = 0; i <= end; i++){
currSum += array[i];
if (currSum > midtoRightMax){
midtoRightMax = currSum;
}
}
if (midtoLeftMax >= 0 && midtoRightMax >= 0){
midMax = midtoLeftMax + midtoRightMax;
}
else {
midMax = midtoLeftMax > midtoRightMax ? midtoLeftMax : midtoRightMax;
}
//返回左半部分最大和、有半部分最大和、跨越左半部分和右半部分最大和中最大的一个
max = leftMax > rightMax ? leftMax : rightMax;
max = max > midMax ? max : midMax;
return max;
}
};