每日一题(20) - 最大子序列和

题目来自网络

题目:给出一数组,求出最大连续子序列之和。

思想(1):

(1)负数是不能作为最大子序列的第一个元素的(当然可以是中间区间的某个元素)。

(2)类似地,任何区间之和为负的子序列不可能是最大子序列的前缀。(即,该序列不可能是最大子序列的起始序列)

代码:

#include <iostream>
#include <assert.h>
using namespace std;

/*
思想:负数是不能作为最大子序列的第一个元素的(当然可以是中间区间的某个元素)。
类似地,任何区间之和为负的子序列不可能是最大子序列的前缀
(即,该序列不可能是最大子序列的起始序列)
*/
int MaxSubSum(int arr[],int nStart,int nEnd)
{
	assert(arr != NULL && nStart <= nEnd && nStart >= 0 && nEnd >= 0);
	int nSubSum = arr[nStart];
	int nMaxSubSum = arr[nStart]; //不能写成0,否则不适合序列全是负数的情况
	int nCurStart = nStart;

	int nMaxStart = nStart;
	int nMaxEnd = nStart;

	for (int i = nStart + 1;i <= nEnd;i++)
	{
		if (nSubSum < 0)
		{
			nSubSum = arr[i];
			nCurStart = i;
		}
		else
		{
			nSubSum += arr[i];
		}

		if (nSubSum > nMaxSubSum)
		{
			nMaxSubSum = nSubSum;

			nMaxStart = nCurStart;
			nMaxEnd = i;
		}
	}

	cout<<"下标区间:"<<nMaxStart<<" - "<<nMaxEnd<<endl;  
	return nMaxSubSum;
}

int main()
{
 	int arr[8] = {4,-3,5,-2,-1,2,6,-2};
 	cout<<MaxSubSum(arr,0,7)<<endl;
 	int arr1[8] = {4,-3,5,-11,4,-2,5,-2};
 	cout<<MaxSubSum(arr1,0,7)<<endl;
 	int arr2[8] = {-3,-5,-8,-2,-11,-12,-13,-1};
 	cout<<MaxSubSum(arr2,0,7)<<endl;
	int arr3[8] = {-1,0,-4};
	cout<<MaxSubSum(arr3,0,2)<<endl;
	int arr4[4] = {-1,2,-4,1};
	cout<<MaxSubSum(arr4,0,3)<<endl;
	system("pause");
	return 1;
}

注意:

(1)如果题目要求是,结果和为负数,则直接返回0.

此时,只需要修改变量nMaxSubSum,令其初始化时 nMaxSubSum = 0。

(2)这里的方法不能求出子序列的具体位置

思路(2)

利用DP来做,这里使用一维数组保存状态,也可以使用一个变量保存最大值,代码略。

#include <iostream>
#include <assert.h>
using namespace std;

/*
F[i]:表示从某个元素开始且第i个元素结尾的子数组最大和

F[i] = F[i - 1] + nArr[i]; i > 0 && F[i - 1] > 0
F[i] = nArr[i];i = 0 || F[i - 1] <= 0  */
int MaxSubSum(int nArr[],int nLen)
{
	int nCurStart = 0;
	int nStart = 0;
	int nEnd = 0;
	
	int F[100];
	int nMaxSum = nArr[0];
	F[0] = nArr[0];

	for (int i = 1;i < nLen;i++)
	{
		if (F[i - 1] > 0)
		{
			F[i] = F[i - 1] + nArr[i];
		}
		else
		{
			F[i] = nArr[i];
			nCurStart = i;
		}

		if (F[i] > nMaxSum)
		{
			nMaxSum = F[i];
			nEnd = i;
			nStart = nCurStart;
		}
	}

	cout<<"下标区间:"<<nStart<<" - "<<nEnd<<endl;

	return nMaxSum;
}

int main()
{
	int nArr[8] = {4,-3,5,-2,-1,2,6,-2};
	int nLen = 8;
//	int nArr[6] = {-2,11,-4,13,-5,-2};
//	int nLen = 6;

// 	int nArr[8] = {-1,-1,-1,-1,-1,-1,-1,-1};
// 	int nLen = 8;

// 	int nArr[6] = {-1,-2,0,1,-4,10};
// 	int nLen = 6;

	cout<<MaxSubSum(nArr,nLen)<<endl;
	system("pause");
	return 1;
}

你可能感兴趣的:(每日一题(20) - 最大子序列和)