连续子数组的最大和

求连续子数组的最大和:这里我就把我自己理解的动态规划算法按照自己的理解写一下

动态规划:

分析:

已知:数组arry[1~n]

问题:如果现在我们已经知道了arry[1~i-1](i>1)中连续子数组的最大和,那么如果扩展到arry[1~i]数组中连续子数组的最大和呢?

求解:假设现在我们已经知道了这个最大的连续子数组,那么这个连续的子数组要么包含arry[i]元素,要么不包含arry[i]这个元素

1)如果包含arry[i]元素,那就是以arry[i]结尾的连续子数组的和;

2)如果不包含arry[i]这个元素,那么就是arry[1~i-1]中连续子数组的最大和;

记maxEndingHere[i]:以arry[i]结尾的连续子数组的和;

记maxSofar[i]:arry[1~i]数组中最大的连续子数组和;

故递推表达式:maxSofar[i] = max(maxSofar[i-1], maxEndingHere[i]);

问题一:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组,求子数组的和的最大值

如果数组中都是负数时,最大总和子向量是绝对值最小的那个负数;

#include <iostream>
using namespace std;

/*
题目:输入一个整型数组,数组里有正数也有负数。
数组中一个或连续的多个整数组成一个子数组。
求子数组的和的最大值。
*/
const int MINVALUE = -1000;

//数组arry的0位置处不存有任何数
void longSubArry(int arry[], int n)
{
	int maxEndingHere = MINVALUE;
	int maxSofar = MINVALUE;
	int maxEndingHereBeginIndex = 0;
	int maxEndingHereEndIndex = 0;
	int maxSofarBeginIndex = 0;
	int maxSofarEndIndex = 0;
	for (int i = 1; i<=n; i++)
	{
		//maxEndingHere表示以arry[i-1]结尾的连续子数组的最大和,求以arry[i]结尾的连续子数组的最大和
		if (maxEndingHere<=0)    
		{
			maxEndingHere = arry[i];    
			maxEndingHereBeginIndex = i;
			maxEndingHereEndIndex = i;
		}
		else
		{
			maxEndingHere = maxEndingHere + arry[i];
			maxEndingHereEndIndex = i;
		}
		if (maxEndingHere >= maxSofar)   //将以arry[i]结尾的连续子数组的最大和 与 arry[1~i]数组中最大连续子数组的和进行刚比较
		{
			maxSofar = maxEndingHere;
			maxSofarBeginIndex = maxEndingHereBeginIndex;
			maxSofarEndIndex = maxEndingHereEndIndex;
		}
			
	}
	cout<<"连续子数组最大的和为:"<<maxSofar<<",开始位置为:"<<maxSofarBeginIndex<<",结束位置为:"<<maxSofarEndIndex<<endl;
}

int main()
{
	int arry[] = {0, 1, -2, 3, 10, -4, 7, 2, -5};
	longSubArry(arry, 8);
	int arryB[] =  {0, -1, -2, -3, -10, -4, -7, -2, -5};
	longSubArry(arryB, 8);

	int arryC[] = {0, 1, 2, 3, 10, 4, 7, 2, 5};
	longSubArry(arryC, 8);
	system("pause");
	return 0;
}

问题二:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组,求子数组的和的最大值

如果数组中都是负数时,最大总和子向量为空,和为0;(有了这个区别,连续子数组的和的最小为0)

void longSubArrySecond(int arry[], int n)
{
	int maxEndingHere = 0;
	int maxSofar = 0;
	int maxEndingHereBeginIndex = 0;  //表示子数组中不包含任何元素
	int maxEndingHereEndIndex = 0;
	int maxSofarBeginIndex = 0;
	int maxSofarEndIndex = 0;

	for (int i = 1; i<=n; i++)
	{
		//以arry[i-1]结尾的连续子数组的最大和要么是正数要么是0
		//现在要求以arry[i]结尾的连续子数组的最大和
		//因为要记录开始索引和结束索引,写的就比较麻烦
		/*if(maxEndingHere > 0 && (maxEndingHere + arry[i]) >0)
		{
			maxEndingHere = maxEndingHere + arry[i];
			maxEndingHereEndIndex = i;
		}
		else if(maxEndingHere > 0 && (maxEndingHere + arry[i])<=0)
		{
			maxEndingHere = 0;
			maxEndingHereBeginIndex = 0;
			maxEndingHereEndIndex = 0;
		}
		else if (maxEndingHere == 0 && arry[i]>0)
		{
			maxEndingHere = arry[i];
			maxEndingHereBeginIndex = i;   //this is very important
			maxEndingHereEndIndex = i;
		}
		else if(maxEndingHere == 0 && arry[i] <=0)
		{
			maxEndingHere = 0;
			maxEndingHereBeginIndex = 0;
			maxEndingHereEndIndex = 0;
		}*/以上这些代码写的有些麻烦,可改进

                //计算maxEndingHere[i]
                if (maxEndingHere <= 0)//注意要包含0
                {
                        maxEndingHere = arry[i];
                        maxEndingHereBeginIndex = i;
                        maxEndingHereEndIndex = i;
                }
                else
                {
                    maxEndingHere = maxEndingHere + arry[i];
                    maxEndingHereEndIndex = i;
                }
                 
                //计算maxSofar[i]
                if (maxSofar <= maxEndingHere)
		{
			maxSofar = maxEndingHere;
			maxSofarBeginIndex = maxEndingHereBeginIndex;
			maxSofarEndIndex = maxEndingHereEndIndex;
		}
	}	
	cout<<"连续子数组最大的和(全为负数即为0)为:"<<maxSofar<<",开始位置为:"<<maxSofarBeginIndex<<",结束位置为:"<<maxSofarEndIndex<<endl;
}

在写这些函数的时候,我的错误就出在:

根据 以aryy[i-1]结尾的连续子数组的最大和 来求 以arry[i]结尾的连续子数组的最大值;不同题目的需求导致我们代码考虑就不一样~~~~~~其实粗略看,两者的代码是相同的。不同的地方就在于maxEndingHere和maxSofar的初始值赋值!

其实这个连续子数组是有多个的,以上解法只是求一个最优解!我目前还没想好如何求所有的解(连续子数组)




你可能感兴趣的:(连续子数组的最大和)