最大子数组问题

小渣今天再来更新一波,欢迎看众 老爷们尽情喷(批评指导)

何为最大子数组:简言之,就是一数组A[n]中从i到j的连续子序列(i,j均在(0,n)区间内),且不存在另一对(a,b)对使得A[a]+A[a+1]+.....A[b]>A[i]+A[i+1]+...+A[j]

可见:①只有在数组含有负数元素时这个问题才有探讨的价值,否则整个数组本身即是最大子数组了;

②并且,i<=j(最大子数组可能只含有一个元素)

③最大子数组可能不唯一

思路:按照二分法来做,最大子数组两端无非有三种情况:

在左半部分,在右半部分,包含中点位置元素

找出三种情形中子数组和最大的那个作为结果,只有前两种情况是可以递归的哦

# include <iostream.h>
# include "..\Sort\IO_tools.cpp"
/*
subarray封装一次查找中得到的最大子数组的两端和该子数组的元素之和
*/
struct subarray{
  int l,r,sum;
};
subarray Find_Max_Cross_SubArray(int A[],int l,int r);//寻找数组A中从l到r索引区间内包含该子数组中点位置的最大子数组
subarray Find_Max_SubArray(int A[],int l,int r);//递归查找数组A中从l到r索引区间内的最大子数组(取三种情况中子数组元素之和最大的作为返回值)
void main(){
    /*
	初值化测试对象
	*/
  int A[6];
  inputA(A,6);
  outputA(A,6);
  /*
  得到最大子数组
  */
  subarray Sub=Find_Max_SubArray(A,0,5);
  /*
  输出
  */
  cout<<"Result:"<<Sub.l<<"  "<<Sub.r<<"  "<<Sub.sum<<endl;
}
subarray Find_Max_SubArray(int A[],int l,int r){
	subarray s1,s2,s3,s4;
	/*
	对于包含两个以上元素的子数组,都要拆半计算
	*/
	if(l<r){
		int mid=(l+r)/2;
		s1=Find_Max_SubArray(A,l,mid);//情况一
		s2=Find_Max_SubArray(A,mid+1,r);//情况二
		s3=Find_Max_Cross_SubArray(A,l,r);//情况三
		/*
		得到l,r索引区间内A的最大子数组
		*/
		s4=s1.sum>=s2.sum?s1:s2;
		s4=s4.sum>=s3.sum?s4:s3;
		/*
		对于含有两个(或以上)元素的区间输出一条调试信息,可以核查自己的思路和代码书写有没有文艺,并且加深领会算法思路
		*/
		cout<<"analyse-:"<<s3.l<<"  "<<s3.r<<"  "<<s3.sum<<endl;
	}
	/*
	只包含一个元素:拆分到底了,即到达了递归的边界
	*/
	else{
		s4.l=s4.r=l;
		s4.sum=A[l];
	}
	/*
	输出本次查找的结果
	*/
    cout<<"analyse:"<<s4.l<<"  "<<s4.r<<"  "<<s4.sum<<endl;
	return s4;
}
/*
因为横跨两部分的子数组显然不是递归解决的,自然是要拉出来单独做:从中点向左最大子数组并上从中点向右子数组即是横跨两半的最大子数组
*/
subarray Find_Max_Cross_SubArray(int A[],int l,int r){
	int left_sum,right_sum,max_left,max_right,sum,mid;
	subarray s;
	left_sum=right_sum=-999;//当做-负无穷看好了,再小也不会比中点元素小,所以这个“负无穷不会传递到结果中去”
	sum=0;
	mid=(r+l)/2;
	for(int i=mid;i>=l;i--){//从中点开始遍历左半部分
	    sum=sum+A[i];
		if(sum>left_sum){
		   left_sum=sum;//只在和增大的情况下更新记录
		   max_left=i;
		}
	}
	sum=0;
	/*分析方法同上*/
	for(int j=mid+1;j<=r;j++){
	    sum+=A[j];
		if(sum>right_sum){
		    right_sum=sum;
			max_right=j;
		}
	}
	/*合并结果*/
	s.l=max_left;
	s.r=max_right;
	s.sum=left_sum+right_sum;
	return s;
}

 该问题的实际应用:

算法导论分治策略里的一个例子,大家自己看就好

时间: 2024-08-08 10:23:39

最大子数组问题的相关文章

软件工程课程作业(四)--返回一个整数数组中最大子数组的和

伙伴链接:http://www.cnblogs.com/haoying1994/ 一.设计思想 本实验要求输入一个正负数混合的整型数组,长度不限,在此数组的所有子数组中找到和最大的数组,并求出相应数组的和,且时间复杂度为O(n).我们在课堂上共同讨论了多种解决方案,这些将在下面可能的解决方案中展示,在听了同学的思路和老师的讲解之后, 我们最终选取了老师课堂上描述的比较简便的思路.如下: 在输入数组的环节,采用for无限循环加if判断截止,直到触发回车键为止,将数组记录到Array中,数组长度记录

lincode.41 最大子数组

最大子数组 描述 笔记 数据 评测 给定一个整数数组,找到一个具有最大和的子数组,返回其最大和. 注意事项 子数组最少包含一个数 您在真实的面试中是否遇到过这个题? Yes 哪家公司问你的这个题? Airbnb Amazon LinkedIn Cryptic Studios Dropbox Apple Epic Systems TinyCo Yelp Hedvig Zenefits Uber Snapchat Yahoo Microsoft Bloomberg Facebook Google T

分治策略 &nbsp; 最大子数组问题

递归式 递归式与分治方法是紧密相关的,因为使用递归式可以很自然地刻画分治算法的运行时间.一个递归式就是一个等式或不等式,它通过更小的输入上的函数值来描述一个函数.例如,在2.3.2节,我们用递归式描述了MERGE-SORT过程的最坏情况运行时间T(n): Θ(1)        若n=1 T(n) =                         (4.1) 2T(n/2)+Θ(n)    若n>1 求解可得T(n)=Θ(nlgn) 递归式可以有很多形式.例如,一个递归算法可能将问题划分为规模

首尾相连求最大子数组和

题目要求: 1.输入一个一维整形数组,数组里有正数也有负数. 2.一维数组首尾相接,象个一条首尾相接带子一样. 3.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值. 设计思想: 遍历数组里面的每一个数将第一个数变为最后一个数,具体算法 a[i-1]=a[i],这样又变成了一个新的一维数组,输出每个数组的最大子数组和,然后比较每个输出的和,找出最大的数 代码: import java.util.Scanner; public class shuzu { p

结对开发——返回整数数组最大子数组和2

返回整数数组最大子数组和2 为了实现“敏捷开发”的目的,老师让我们采取“迭代”的方法进行项目的开发,这不,对于周一的求最大子数组和又有了新的要求,如下: 1.延续上次的要求,这里不再赘余… 2.如果数组A[0]……A[j-1]首尾相连,允许A[i-1],……A[n-1],A[0]……A[j-1]之和最大: 3.同时返回最大子数组的位置: 4.要求程序必须能处理1000 个元素,且每个元素是int32 类型的. 一.实验设计思路 首先实现的是数组首尾相连,先存入数组,再将原数组反向存储形成环形数组

课后实验4--返回一个整数数组中最大子数组的和

伙伴链接:http://www.cnblogs.com/chengqiqin07/ 一.设计思想 本实验要求输入一个正负数混合的整型数组,长度不限,在此数组的所有子数组中找到和最大的数组,并求出相应数组的和,且时间复杂度为O(n).我们在课堂上共同讨论了多种解决方案,这些将在下面可能的解决方案中展示,在听了同学的思路和老师的讲解之后, 我们最终选取了老师课堂上描述的比较简便的思路.如下: 在输入数组的环节,采用for无限循环加if判断截止,直到触发回车键为止,将数组记录到Array中,数组长度记

lintcode 中等题:maximum subarray difference 最大子数组差

题目 最大子数组差 给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大. 返回这个最大的差值. 样例 给出数组[1, 2, -3, 1],返回 6 注意 子数组最少包含一个数 挑战 时间复杂度为O(n),空间复杂度为O(n) 解题 刚做了数组中两个子数组和的最大值,这一题是求差,感觉上题的求解思想应该是可以用的 A B 分别是两个子数组的和,则: 所以 当A>B 的时候A越大越好 B越小越好 当A<B 的时候B越大越好 A越小越好

最大子数组之和、最大子数组之积、最长递增子序列求法

昨天做爱奇艺笔试题,最后一道编程题是求整型数组最长递增子序列,由于时间关系,没有完全写出来,今天重新来做做这一系列题. <1> 最大子数组之和 首先从最简单的最大子数组之和求取.数组里有正数.负数.零.设包含第 i 个元素的子数组的和为 Sum,则Sum的值为 Sum(i) = Sum(i-1) + arrey[i]; 显然如果arrey[i]<=0,则Sum(i)<=Sum(i-1);则必须把Sum(i)=arrey[i];同时maxSum用来保存Sum最大值.时间复杂度为o(n

(算法)最大子数组和以及最大子矩阵和

题目: 1.给定一数组,求该数组的最大子数组和: 2.给定一矩阵,求该矩阵的最大子矩阵和: 思路: 1.求数组的最大子数组和很简单,可以通过动态规划来实现,假设数组为arr: 假设dp[i]表示从0到i的数组的最大子数组和,那么递推关系式表示为: dp[0]=arr[0]; dp[i]=dp[i-1]>0?dp[i-1]+arr[i]:arr[i] 2.求矩阵的最大子矩阵和看似很难,其实也可以转化为最大子数组和的问题.假设矩阵为matrix 首先,我们求出矩阵每个位置按行叠加的结果,设叠加结果矩