问题描述:求{ -2,1,-3,4,-1,2,1,-5,4 }中和最大的子序列
算法1:枚举法,复杂度为O(n^3)
int MaxSubArray_1(const vector<int> &a) {
int MaxSum = 0;
for (int i = 0; i < a.size(); i++) {
for (int j = i; j < a.size(); j++) {
int this_sum = 0;
for (int k = i; k <= j; k++) {
this_sum += a[k];
}
if (this_sum > MaxSum) {
MaxSum = this_sum;
}
}
}
return MaxSum;
}
算法2:改进的枚举法,复杂度为O(n^2)
int MaxSubArray_2(const vector<int>& a) {
int MaxSum = 0;
for (int i = 0; i < a.size(); i++) {
int this_sum = 0;
for (int j = i; j < a.size(); j++) {
this_sum += a[j];
if (this_sum > MaxSum)
MaxSum = this_sum;
}
}
return MaxSum;
}
算法3:分治法,复杂度O(nlogn)
最大子序列有三种可能出现的位置:序列的前半部分、后半部分和中间,前半部分和后半部分使用递归计算,中间部分分别从中间向两边查找,三个部分中最大的序列即和最大子序列。
int MaxSubArray_3(const vector<int>& a, int left, int right) {
if (left == right) {
if (a[left] > 0) {
return a[left];
}
else return 0;
}
int MaxSum = 0;
int MaxLeft = 0;
int MaxRight = 0;
int MaxCenter = 0;
int center = (left + right) / 2;
MaxLeft = MaxSubArray_3(a,left,center);
MaxRight = MaxSubArray_3(a,center+1, right);
int MaxCenterLeft = 0;
int CenterLeftSum = 0;
for (int i = center; i >= left; i--) {
CenterLeftSum += a[i];
if (CenterLeftSum > MaxCenterLeft)
MaxCenterLeft = CenterLeftSum;
}
int MaxCenterRight = 0;
int CenterRightSum = 0;
for (int i = center+1; i <= right; i++) {
CenterRightSum += a[i];
if (CenterRightSum > MaxCenterRight)
MaxCenterRight = CenterRightSum;
}
MaxCenter = MaxCenterLeft + MaxCenterRight;
MaxSum = MaxLeft;
if (MaxRight > MaxSum) {
MaxSum = MaxRight;
}
if (MaxCenter > MaxSum) {
MaxSum = MaxCenter;
}
return MaxSum;
}
注意,在递归时,一定要记得写递归终止条件,否则会无限的占用堆栈,出现stack overflow的错误。
算法四:扫描法
只需要一次遍历,遍历的过程中把和为负的子序列抛弃
int MaxSubArray_4(const vector<int>& a) {
int MaxSum = 0;
int thisSum = 0;
for (int i = 0; i < a.size(); i++) {
thisSum += a[i];
if (thisSum > MaxSum)
MaxSum = thisSum;
else if (thisSum < 0)
thisSum = 0;
}
return MaxSum;
}
时间复杂度为O(n)
输出结果:
int main() {
vector<int> a = { -2,1,-3,4,-1,2,1,-5,4 };
int num = a.size();
Solution solution;
cout << "算法1的输出是:"<<solution.MaxSubArray_1(a)<<'\n';
cout << "算法2的输出是:" << solution.MaxSubArray_2(a)<<'\n';
cout << "算法3的输出是:" << solution.MaxSubArray_3(a,0, num - 1)<<'\n';
cout << "算法4的输出是:" << solution.MaxSubArray_4(a) << '\n';
}
提交Leetcode.53
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int MaxSum = 0;
int thisSum = 0;
int size_nums = nums.size(); //把size的过程记录下来,减少了4ms的用时
int i = 0;
for(i = 0; i < size_nums; i++){
thisSum += nums[i];
if(thisSum > MaxSum)
MaxSum = thisSum;
else if(thisSum < 0)
thisSum = 0;
}
//检查全小于零的情况
int pos_flag = 0;
if(MaxSum == 0){
for(i = 0; i < size_nums; i++){
if(nums[i] >= 0){
pos_flag = 1;
break;
}
}
if(pos_flag == 0){
int big = nums[0];
for(i = 1; i < size_nums; i++){
if(nums[i] > big)
big = nums[i];
}
MaxSum = big;
}
}
return MaxSum;
}
};
效果并不理想,以后再改进