编程之美之子数组之和的最大值以及扩展(可首尾相连)

情形一:不允许首尾相连

此情况很常见,方法是动态规划,编程之美的方法三给出了解法,这里就直接给出代码了

int maxSubSum(vector<int>& data)
{
	int length = data.size();
	assert(length >= 0);
	int maxSum = data[length-1],startSum = data[length-1],begin = length-1,i;
	for(i = length-2;i >= 0;i--)
	{
		startSum = max(data[i],data[i]+startSum);//以第i个数开头的最大子数组之和
		if(startSum > maxSum)
		{
			begin = i;
			maxSum = startSum;//当前的最大子数组之和
		}
	}
	startSum = 0;
	for(;begin < length && startSum != maxSum;startSum+=data[begin],begin++)cout << data[begin] << " ";
	cout << endl;
	return maxSum;
}

情形二、数组可以首尾相连

问题的解可以分为两种情况:

1)解没有跨过A[n-1]到A[0],即普通的求子数组和的最大值

2)解跨过A[n-1]到A[0]

对于第2种情况包含两种可能(2.1)包含整个数组;(2.2)包含两个部分,从A[0]开始的一段以及以A[n-1]结尾的一段,这种情况相当于从数组A中删除一个和最小的一个子数组,而当最小和为0时,即全为非0元素时,此时又和(2.1)一样。而个人认为解跨过A[n-1]到A[0]的情况肯定大于没有跨过的情况,所以,最后的结果就是所有元素的和减去绝对值最大的负数子数组,具体代码如下:

int maxSubSumEndToEnd(vector<int>& data)
{
	int length = data.size();
	assert(length >= 0);
	int minSum = data[length-1],startSum = data[length-1],allSum = data[length-1],begin = length-1,i,j;
	for(i = length-2;i >= 0;i--)
	{
		allSum += data[i];
		startSum = min(data[i],data[i]+startSum);
		if(startSum < minSum)
		{
			begin = i;
			minSum = startSum;//求绝对值最大的负数子数组
		}
	}
	if(minSum > 0)
	{
		minSum = 0;
		begin = 0;
	}
	startSum = 0;
	j = begin;
	for(;j < length && startSum != minSum;startSum+=data[j],j = (j + 1)%length);//找到开始的位置j
	for(i = j;i != begin;i = (i+1)%length)cout << data[i] << " ";
	cout << endl;
	return (allSum - minSum);
}

如有问题,请指正,谢谢

时间: 2024-10-28 09:00:38

编程之美之子数组之和的最大值以及扩展(可首尾相连)的相关文章

求数组的子数组之和的最大值及扩展问题2

这是一道来自<编程之美>2.14节的题目. 这篇博文把思路写了一下.在此我要特别说明的是方法二和方法三的自己写的东西. 我把方法二的分治法用C++实现了一下,代码如下: int MAX(int a,int b,int c) { int t=a>b?a:b; return t>c?t:c; } int Array(int a[],int i,int j) { if (i<j) { int q=(i+j)/2,sum1=0,sum2=0,k,Max1=-0x7fffffff,Ma

第2章 数字之魅——求数组的子数组之和的最大值

求数组的子数组之和的最大值 问题描述 分析与解法 [解法一] 具体代码如下: 1 package chapter2shuzizhimei.maxsumsubarray; 2 /** 3 * 求数组的子数组之和的最大值 4 * [解法一] 5 * @author DELL 6 * 7 */ 8 public class MaxSumSubArray1 { 9 //求数组的子数组之和的最大值 10 public static double maxSum(double a[]){ 11 double

编程之美之2.14 求数组的子数组之和的最大值

[题目] 一个有N个整数元素的一维数组(A[0],A[1],A[2],...A[n-1]),这个数组中当然有很多子数组,那么子数组之和的最大值是多少? 该子数组是连续的. 我们先来明确一下题意: (1)子数组意味着是连续的. (2)题目只需要求和,并不需要返回子数组的具体位置. (3)数组的元素是整数,所以数组可能包含正整数,负整数或者零. 举几个例子: 数组:[1,-2,3,5,-3,2]返回8 数组:[0,-2,3,5,-1,2]返回9 数组:[-9,-2,-3,-5,-3]返回8 [解法一

[编程之美] 2.14 求数组的子数组之和的最大值

问题描述:给定一个包含N个整数的数组,求数组的子数组之和的最大值. 这是递归和贪心策略的一个经典问题.现在,对这个问题进行一下总结. 1 明确题意 题目中的子数组要求是连续的,也就是数组中的某个连续部分. 如果数组中都是正整数,直接相加就行.因此,主要是要考虑负数的情况. 2 直接求所有的子数组和 最简单且容易理解的解法是求出所有的子数组和,然后保存最大的和. int MaxSum(int *A, int n) { int maximum = -INF; int sum = 0; int i =

编程之美读书笔记2.14 - 子数组之和的最大值

http://blog.csdn.net/pipisorry/article/details/39083281 问题: 1. 一个由N个整数元素的一维数组,求其所有子数组中元素和的最大值. 2. 如果数组首尾相邻,也就是允许子数组A[i],...,A[n-1],A[0],...,A[j]存在,求其所有子数组总元素和的最大值. 解法1: /* O(n^2) 遍历算法 */ static int maxSubarraySum1(int *a,int a_len){ int max_sum = INT

编程之美 2.14求数组的子数组之和的最大值

对于一个有N个元素的数组,a[0]~a[n-1],求子数组最大值. 如:数组A[] = [−2, 1, −3, 4, −1, 2, 1, −5, 4],则连续的子序列[4,−1,2,1]有最大的和6. 方法一:暴力 循环遍历,输出所有,判断最大的和 1 #include"iostream" 2 #define MAX 1001 3 using namespace std; 4 5 int main(){ 6 int n, a[MAX], sum , maxsum ; 7 8 cin &

编程之美2.14 求数组的子数组之和的最大值

问题描述: 一个有N个整数元素的一维数组(A[0], A[1], A[2],...,A[n-1]),这个数组当然有很多子数组,那么子数组之和的最大值是什么呢? 解法: 1. 暴力解法-------O(N^3) 2. 改进版暴力解法-------O(N^2) *3. 分治算法-------O(NlogN)(暂时未去实现) 4. 数组间关系法-------O(N) 具体思路和代码: 1.暴力解法 思路:Sum[i,...,j]为数组第i个元素到第j个元素的和,遍历所有可能的Sum[i,...,j].

求数组的子数组之和的最大值?

自己写的代码考虑未周全,引入了额外的空间复杂度: //求数组的子数组之和的最大值 #include <iostream> #define N 12 using namespace std; int main() { //int a[]={-5,2,3,-3,-2,3,1,-5}; //int a[]={-5,2,0,3,-2,3,4,5}; int a[]={1,-2,3,10,-4,7,2,-5}; int flag,max,i,j=0; int sum[N]={0}; //(1)记录子数组

第2章 数字之魅——子数组之和的最大值(二维)

子数组之和的最大值(二维) 问题描述 我们在前面分析了一维数组之和的最大值问题,那么如果是二维数组又该如何分析呢? 分析与解法 最直接的方法,当然就是枚举每一个矩形区域,然后再求这个矩形区域中元素的和. [解法一] 完整代码如下: 1 package chapter2shuzizhimei.maxsumsubarraytwodimensional; 2 /** 3 * 求数组的子数组之和的最大值(二维) 4 * [解法一] 5 * @author DELL 6 * 7 */ 8 public c