算法1:最大子序列和

问题描述:求{ -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;
    }
};

在这里插入图片描述
效果并不理想,以后再改进

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值