求整数数组中和最大的子数组的3种方法
2013-03-09 21:16
302 查看
输入一个整型数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。
使用三种方式实现,分别是蛮力法:bf_MaxSubArray,分治法:dc_MaxArray,和O(n)实现的单循环法find_max。
其中最优方法的参考地址:求整数数组中和最大的子数组
使用三种方式实现,分别是蛮力法:bf_MaxSubArray,分治法:dc_MaxArray,和O(n)实现的单循环法find_max。
#include"stdio.h" #include"math.h" #include"time.h" #include"windows.h" #define MIN_INT -10000 #define MAX_INT 10000 typedef struct{ int max_left; int max_right; int max; }maxinfo; maxinfo bf_MaxSubArray(int *a,int n) { maxinfo max; max.max_left= 0; max.max_right= 0; max.max= MIN_INT; int tmp=0; for(int i=0;i<n;i++) { for(int j=i;j<n;j++) { tmp += a[j]; if(tmp > max.max) { max.max = tmp; max.max_left = i; max.max_right = j; } } tmp = 0; } return max; } maxinfo dc_FindMaxCrossingSubArray(int *a,int left,int mid,int right) { maxinfo leftMax; leftMax.max_left= mid; leftMax.max_right = mid; leftMax.max= MIN_INT; int tmp = 0; for(int i=mid;i>=left;i--) { tmp += a[i]; if(tmp>leftMax.max) { leftMax.max = tmp; leftMax.max_left = i; } } maxinfo rightMax; rightMax.max_left=mid+1; rightMax.max_right = mid+1; rightMax.max= MIN_INT; tmp = 0; for(int j = mid+1;j<right+1;j++) { tmp += a[j]; if(tmp>rightMax.max) { rightMax.max = tmp; rightMax.max_right = j; } } leftMax.max += rightMax.max; leftMax.max_right = rightMax.max_right; return leftMax; } maxinfo dc_MaxArray(int *a,int left,int right) { if(left==right) { maxinfo sgele; sgele.max_left=left; sgele.max_right = right; sgele.max= a[left]; return sgele; } else { int mid = (int)floor((left+right)/2); maxinfo tmp; maxinfo maxleft = dc_MaxArray(a,left,mid); maxinfo maxright = dc_MaxArray(a,mid+1,right); maxinfo maxcross = dc_FindMaxCrossingSubArray(a,left,mid,right); tmp = maxleft.max>maxright.max?maxleft:maxright; tmp = tmp.max>maxcross.max?tmp:maxcross; return tmp; } } void show(maxinfo max) { printf("收益最大的是:%d号前买入,%d号后卖出,收益$%d/股.\n",max.max_left+1,max.max_right+1,max.max); } void find_max(int *ary,int ARYSIZE) { int max=0;//保存最大和 int curSum=0;//保存当前和 int curStart=0;//当前和的起始位置 int start=0;//最大和的起始位置 int end=0;//最大和的终止位置 for(int i=0;i<ARYSIZE;i++) { if(i==0) { curSum=max=ary[i]; continue; } if(curSum<0) { curSum=0;//与负数相加,和会减小,所以抛弃以前的和 curStart=i; } //最大值已经被保存下来,所以请大胆的继续往前加 curSum += ary[i]; //当前和被保存为最大值,记录下它的起始位置和结束位置 if(curSum>max) { max=curSum; start=curStart; end=i; } } printf("和最大的子数组为:\n"); for(int j=start;j<=end;j++) { printf("%d ",ary[j]); } printf("= %d",max); } void main() { int n = 16; int a[] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7}; //{-13,-3,-25,-20,-3,-16,-23,-18,-20,-7,-12,-5,-22,-15,-4,-7};// int i=clock(); show(bf_MaxSubArray(a,n)); printf("\n==============\n"); find_max(a,n); printf("\n==============\n"); printf("计算耗时:%dms\n",clock()-i); int mid = (int)floor((n-1)/2); show(dc_FindMaxCrossingSubArray(a,0,mid,n-1)); maxinfo result; LARGE_INTEGER nFreq; LARGE_INTEGER nBeginTime; LARGE_INTEGER nEndTime; double time; QueryPerformanceFrequency(&nFreq); QueryPerformanceCounter(&nBeginTime); //开始 result = bf_MaxSubArray(a,n);//dc_MaxArray(a,0,n-1); QueryPerformanceCounter(&nEndTime); time=(double)(nEndTime.QuadPart-nBeginTime.QuadPart)/(double)nFreq.QuadPart; printf("%f微妙\n",time); show(result); printf("\n"); }
其中最优方法的参考地址:求整数数组中和最大的子数组
相关文章推荐
- LintCode 最大子数组(3种方法)
- 求一个整数数组的最大元素,用递归方法实现
- 求整数数组中和最大的子数组
- 求整数数组中和最大的子数组
- 给一个整数数组,对数组中的每个整数中的所有数字按照升序排列(如101排序后为011)请写一个方法,输出排序后的数组中的最大数。 例如有一个数组: 101、132、375,排序后11、123、357,
- 面试题,求一个整数数组中和最大的连续子数组,例如:[1, 2, -4, 4, 10, -3, 4, -5, 1]的最大连续子数组是[4, 10, -3, 4](需写明思路,并编程实现)
- 求整数数组中和最大的子数组
- Java利用递归的方法求整数数组中的最大值
- 求一个整数数组中和最大的连续子数组,例如:[1, 2, -4, 4, 10, -3, 4, -5, 1]的最大连续子数组是[4, 10, -3, 4](需写明思路,并编程实现)
- C - 求整数数组中和最大子串
- 求整数数组中和最大的子数组
- 输入整形数组,数组里有正数也有负数,数组中一个或连续的多个整数组成数组的子数组,求所有子数组中和的最大值 ,例如输入的数组为{1,-2,3,10,-4,7,2,-5}和最大的子数组为{3,10,
- 求整数数组中和最大的子数组
- 完全理解递归与分治:3种方法求数组最大值为例子
- 求一个整数数组的最大元素,用递归方法实现
- 数组方法关于任意数字类型的数组求最大值解决办法
- 随机10个100到200之间的整数,将这些数放入数组中,打印数组,再使用 3种排序。
- 一个整数数组,长度为n,将其分为m 份,使各份的和相等,求m 的最大值
- 修改MYSQL最大连接数的3种方法
- 面试题系列-整数数组长度为n,分为m份使各份的和相等,求最大的m