最大子序列和

题目:

给定一个整数序列(数组)nums ,找到一个具有最大和的连续子序列(子序列最少包含一个元素),返回其最大和

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
原因: 连续子数组 [4,-1,2,1] 的和最大,为 6

代码:

方法一:暴力循环

#include <iostream>
#define _for(a,b,c) for(int a=b;a<c;a++)
using namespace std;
int main()
{
	int nums[9] = {-2,1,-3,4,-1,2,1,-5,4};
	int k = sizeof(nums)/sizeof(nums[0]);//nums是数组 
	int max_sum = nums[0];
	_for(i,0,k)
	{
		int sum = 0;
		_for(j,i,k)
		{
			sum+=nums[j];
			if(sum>max_sum) max_sum = sum;
		}
	}
	cout<<max_sum;
	return 0;
}

在这里插入图片描述
复杂度为 O(n2

此为 leecode 上通过编译显示的数据
顺便说一下,在 leecode 上不能用 sizeof(nums)/sizeof(nums[0]) ,会报错,应用 nums.size() ,因为 leecode 输入的是 vector容器,而 vector容器 是存在 nums.size() 方法的

方法二:分治法

#include <iostream>
#define _for(a,b,c) for(int a=b;a<c;a++)
using namespace std;
int fenzhi(int nums[],int left,int right);
int mid2(int nums[],int mid,int left,int right);
int main()
{
	int nums[9] = {-2,1,-3,4,-1,2,1,-5,4};
  	int result = INT_MIN;
    int k = sizeof(nums)/sizeof(nums[0]);
    result = fenzhi(nums,0,k-1);
    cout<<result;
    return 0;
}
int fenzhi(int nums[],int left,int right)
{
  	if(left==right) return nums[left];
   	int mid = (left+right)/2;
   	int leftmax = fenzhi(nums,left,mid); //从 left 开始,而不是 0
   	int rightmax = fenzhi(nums,mid+1,right);
   	int result = max(leftmax,rightmax);
   	int midmax = mid2(nums,mid,left,right);
   	result = max(result,midmax);
   	return result;
}
int mid2(int nums[],int mid,int left,int right)
{
	int leftsum = nums[mid],rightsum = nums[mid+1],sum = 0;
	for(int i = mid;i>=left;i--) leftsum = max(leftsum,(sum+=nums[i]));
	sum = 0;
	for(int i = mid+1;i<=right;i++) rightsum = max(rightsum,(sum+=nums[i]));
	return (leftsum+rightsum); //注意返回值是二者相加,而不是取最大值
}

在这里插入图片描述
复杂度为 O(nlogn,虽然 分治法 复杂度比 暴力法 低,但是对于此题,数据越小, 结果越不明显

再说一些关于 leecode 的事项
leecode 不用考虑定义顺序(即不用写声明直接定义 )
lecode不用写头文件,或相当于自带<bits/stdc++.h> (暂时如此认为)

方法三:贪心

#include <iostream>
#define _for(a,b,c) for(int a=b;a<c;a++)
using namespace std;
int main()
{
	int nums[9] = {-2,1,-3,4,-1,2,1,-5,4};
	int maxSum=nums[0],sum=0;
	int k = sizeof(nums)/sizeof(nums[0]);
	_for(i,0,k)
	{
		sum+=nums[i];
		if(sum>maxSum) maxSum=sum;
		if(sum<0) sum=0;
	}
    cout<<maxSum;
    return 0;
}

在这里插入图片描述
复杂度为 O(n),同理,数据越小, 结果越不明显

此题中,此方法别名:及时处理
因为全程只遍历一遍,故遍历到哪儿,哪儿就是最优解

解析本题贪心
若不理解什么是贪心,建议参考此篇博客:贪心—基本概念,本题的方法主要运用了的思想:先将 sum 和 maxsum 赋值为第一个元素的值,若 sum 小于 0,则重新为 sum 赋值为 0,并加上下一个元素的值,继续累加,若 sum 大于 0,接下来也继续累加,但要在 sum 小于 0 时重新为其赋值为 0,并加上下一个元素的值,继续累加,并每加一次与 maxsum 进行比较、替换

若还是不能理解,不妨看看这句话
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值