标签:
题目:
返回一个整数数组中最大子数组的和。
要求:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大。
同时返回最大子数组的位置。
求所有子数组的和的最大值。
(我主要负责程序分析,代码编程;张金负责代码复审,代码测试计划。)
思路:
与第一次的不同之处,只在于首尾相连,构成了一个环。思路差不多,我们构造了三个数组:(A)arr[]为原数组;(B)Max[]保存以每个元素为头的所有子数组的和的最大值;(C)arrCopy[]将原数组头尾相连构造的新的一维数组。它们的关系如下:
max[0]为{arr[0]、arr[0]+arr[1]、...、arr[0]+arr[1]+...+arr[n-1]+arr[n]}中的最大值;
max[1]为{arr[1]、arr[1]+arr[2]、...、arr[1]+arr[2]+...+arr[n]+arr[1]}中的最大值;
......
max[n-1]为{arr[n-1]、arr[n-1]+arr[n]、...、arr[n-1]+arr[n]+...+arr[n-3]+arr[n-2]}中的最大值;
max[n]为{arr[n]、arr[n]+arr[1]、...、arr[n]+arr[1]+...+arr[n-2]+arr[n-1]}中的最大值。再比较max数组,从中找到最大值。
arrCopy[]为{arr[1]、arr[2]、...、arr[n]、arr[1]、...、arr[n-1]}这样的一个数组,它的的作用则是标记子数组的位置。
<span style="font-family: Microsoft YaHei; font-size: 16px;">#include<iostream.h> #include<stdlib.h> #define AMOUNT 100 int main() { int arr[AMOUNT]; int arrCopy[AMOUNT]; int max[AMOUNT]; int i,j; int n; int head,rear; //子数组的开始,结束 int mount,amount; cout<<"input mount: "; cin>>mount; while(mount<=0) { cout<<"illegal input! Again :"; cin>>mount; } amount=2*mount-1; for(i=0;i<mount;i++) { try { n=rand()%2; if(n==0) { arr[i]=rand()%100; arrCopy[i]=arr[i]; max[i]=arr[i]; } else { arr[i]=-rand()%100; arrCopy[i]=arr[i]; max[i]=arr[i]; } } catch(long int e) { cout<<"Long Inter=ger Exception!"<<endl; } } for(i=0;i<mount;i++) { cout<<arr[i]<<" "; if((i+1)%10==0) { cout<<endl; } } for(i=mount;i<amount;i++) { arr[i]=arr[i-mount]; arrCopy[i]=arr[i]; } for(j=0;j<mount;j++) { for(i=j+1;i<j+mount;i++) { arr[j]=arr[j]+arr[i]; if(max[j]<arr[j]) { max[j]=arr[j]; rear=i+1; if(rear>mount) { rear=rear-mount; } } } } for(i=0;i<mount;i++) { if(max[0]<max[i]) { max[0]=max[i]; head=i+1; } } cout<<endl; cout<<"从第"<<head<<"个数"<<arrCopy[head-1]<<"开始"<<endl; cout<<"到第"<<rear<<"个数"<<arrCopy[rear-1]<<"结束"<<endl; cout<<"子数组和的最大值为: "<<max[0]<<endl; return 0; } </span> |
运行结果:
(1)首先由于没有仔细的考虑,在提示输入数组长度的时候随意输了负数,导致程序不能正常执行,经过修改,能对不符合的数据类型发出错误提示,并且重新输入。
(2)有图可以看到,定义的数组长度为5,和最大的子数组是由第5个数循环至第1个数组成的,但却显示的是arrCopy[]数组中的第6个数,位置不正确。
(3)经过修改,能正确找到环的结束位置。
(4)但是我们自己手动输入的数都很小,所以最后改动:只输入数组长度(截图测试为10),数值随机产生。
总结:
看到题目最先想到的是数据结构中的链表结构,但是很快就把这个思路放弃,感觉用链表比较麻烦,听了课上三位同学的思路,大家的观点其实都是把数组构成一个环状结构,或者构成一个新的一维数组,接着就跟第一次求最大和一样。开始犯难的是在怎么确定子数组的起始元素和结尾元素上,下标的记录是很关键的,因为在我们的算法中,运用递归会不断覆盖原数组的值,造成所有子数组求完和之后,原数组的值发生了改变,而无法返回最大子数组的位置,既然如此,能像到的方法就是把子数组复制一遍,最后定位时可以使用。最后还是数据测试的问题,手动输入具有很大的主观意识,所以还是使用随机数测试比较能发现问题。
感觉现在能解决一些问题了,但方法还是想初学者那般,很多类似时间、空间复杂度那些都没有考虑。
标签:
原文地址:http://www.cnblogs.com/xiaojin123/p/4376517.html