剑指offer:连续子数组的最大和

剑指offer:连续子数组的最大和

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

这个题目描述好长啊。。。。简单的说就是:给你一个数组,让你得到其中的一个连续子数组,这个子数组具有最大的和。

本菜鸡的想法

最一开始最容易想到的肯定是枚举没错了,计算一下所有连续子数组的和,保留最大的。
但这个枚举过程也有一些可以轻易剪掉的分支:以负数为开头的所有连续子数组都可以不用枚举。
但这有一个问题,就是所有的数都是负数呢?所以我设置了一个标志位,如果所有的都是负数,就返回最大负数。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int FindGreatestSumOfSubArray(vector<int> array) 
{
	if (array.size() == 0)
	{
		return 0;
	}
	int res = 0,Max=-9999999;
	int flag = 0, tmp = -9999999;
	for (int i = 0; i < array.size(); i++)
	{
		if (array[i] < 0)
		{
			tmp = max(tmp, array[i]);
			continue;
		}
		else
		{
			flag = 1;
			for (int j = i; j < array.size(); j++)
			{
				res += array[j];
				Max = max(Max, res);
			}
		}
		res = 0;
	}
	if (flag == 0)
	{
		return tmp;
	}
	else
	{
		return Max;
	}
}

int main()
{
	vector<int> vec = { -2,-8,-1,-5,-9 };
	int res = FindGreatestSumOfSubArray(vec);
	cout << res;
}

这种方法不太好,看了别人的方法用的是动态规划

动态规划

首先,状态表示 F[i] ,表示的是以第i个元素结尾的具有最大和的子数组的和。
状态转移方程:F[i] = max(F[i-1]+array[i],array[i])

为什么F[i]要这么定义?最终得到的结果肯定是以某个元素结尾的子数组,所以F[i]定义为 以第i个元素结尾的具有最大和的子数组的和 ,这样,找到所有的F[i]后再找最大的就是答案了。

为什么状态转移方程是这样?F[i]是与F[i-1]有关系的,但F[i-1]可能是负的呀,所以要是负的的话,那还不如自己自成一个子数组。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int FindGreatestSumOfSubArray(vector<int> array)
{
	if (array.size() == 0)
	{
		return 0;
	}
	int res = array[0];   //res是用来存储F[i-1] 
	int Max = array[0];	//max是用来存当前状态下的最大值。
	for (int i = 1; i < array.size(); i++)
	{
		res = max(res + array[i], array[i]);
		Max = max(Max, res);
	}
	return Max;
}

int main()
{
	vector<int> vec = {6,-3,-2,7,-15,1,2,2};
	int result = FindGreatestSumOfSubArray(vec);
	cout << result;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值