最大子数组和02
1、题目要求:
(1)输入一个整形数组,数组里有正数也有负数;
(2)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和;
(3)如果数组A[0]……A[j-1]首位相邻,允许A[i-1],……A[n-1],A[0]……A[i-1]之和最大;
(4)同时返回最大子数组的位置。
2、实现思路:
(1)先要输入一组整形数,直到输入回车结束;
(2)分离出每一个数,按顺序存放到整形数组里;
(3)每一个、相连续两个、三个……都是子数组,分别求出子数组的和,把最大的和输出。
3、思路整理(实现步骤):
(1)输入数组元素,用空格分开,输入的是字符,转化为整形数,连续的0~9字符,按所在数位进行放大求和,得出输入的整形数;
(2)若输入的字符是空格,则将空格前的数存放入整形数组中;
(3)按回车,输入结束,开始计算;
(4)计算过程:
把数组复制一遍,按顺序存放到原数组的后面,生成一个新的数组,长度为原数组的两倍,前后两部分相同;
以下加操作全部只循环n次,以免加到重复的数;
从第一个数开始,依次比较大小,最大的数单独存放在num1;
第一个数,开始,求arr[1]+arr[2]+……+arr[n],将所有和的最大值与num1 比较,最大值存入num1;
再求arr[i]+arr[i+1]+……+arr[k],将所有和的最大值与num1 比较,最大值存入num1;
直到arr[i] 为最后一个数为止,num1 即为子数组最大的和。
4、源代码:
#include <iostream> using namespace std; char arr[1000];//接收数据,并以字符串形式保存 int arr1[100];//保存转换来的整数 int arr2[200];//保存扩大两倍后的数组 int k=0;//计数标志 void chtoin()//将字符形式的数组转为整型 { int i=0; int j=10; int num1=0;//保存每一位数字 int num2=0;//保存数字整体 bool flag=0;//作为正负标志 char ch[]="#"; cout<<"请输入数组(中间以空格隔开):"<<endl; gets(arr); strcat(arr,ch);//将#存在字符数组后,作为结束标志。 for (;;) { if(arr[i]=='#')//遇到#结束,并将#前的数存入整型数组 { if (flag==0)//flag为0,说明读入的数为正数 { arr1[k]=num2; k++; } else//flag为1,说明读入的数为负数 { arr1[k]=0-num2; k++; } break; } else { if (arr[i]==' ')//遇到空格,将空格前一个数存入整型数组 { if (flag==0) { i++; arr1[k]=num2; num2=0; k++; } else { i++; arr1[k]=0-num2; num2=0; flag=0; k++; } } else if (arr[i]=='-')//遇到-,判断为负数,将flag置位1 { i++; flag=1; } else { num1=arr[i]-'0'; num2=num1+num2*j; i++; } } } } void arr1toarr2()//数组扩展函数,将数组扩展到原来的两倍 { int i=0; for(i;i<k;i++) { arr2[i]=arr1[i]; } for (;i<2*k;i++) { arr2[i]=arr1[i-k]; } } void main() { int j=0;//作为每一轮,从第几位开始求和 int i;//作为数组下标 int x=0;//作为移位标志 int y1,y2=0,y3,y4;//y1表示最大数组的首位,y2计算最大数组个数,y3保存中间过程中最大数组长度,y4保存最终长度。 chtoin(); arr1toarr2(); int num1=arr2[0],num2=0,num3=0;//num1保存每一轮的最大值,num2求和,num3保存最终的最大值 for (;;) { i=x;//已经移位到x,i作为数组下标 for(;;) { num2+=arr2[i]; y2++; if (num2>=num1) { y3=y2; num1=num2; } if (j==k+x) { break; } else { if (i==k+x-1) { num2=0; j++; i=j-1; } } i++; } x++; y2=0; if (num3<=num1) { y1=x-1; y4=y3; num3=num1; num2=0; num1=0; } else { num1=0; num2=0; } if (x==k) { break; } } cout<<"最大子数组为:"<<endl; for (int h=y1;h<y1+y4;h++) { cout<<arr2[h]<<" "; } cout<<endl; cout<<"最大子数组和为:"<<endl; cout<<num3<<endl; }
5、运行结果:
6、总结分析:
在这次的题目中,我们并没有费很多的时间,当老师提出这个问题的时候,我就想到了将原数组长度增长一倍,并复制两遍,进行计算
遇到的问题:开始没有想到,要控制计算求和的长度,以至于把同一个数计算了两遍。。。。终于想到,数组长度变了,但求和时长度要控制在原数组的一倍长度以内。
项目计划日志(单位:h):
听课 | 编写程序 | 阅读相关书籍 | 网上查找资料 | 日总计 | |
周一 | 2 | 0 | 1 | 0.5 | 3.5 |
周二 | 0 | 1 | 0.5 | 0 | 1.5 |
周三 | 0 | 2 | 0 | 0 | 2 |
周四 | 2 | 1.5 | 0 | 1.5 | 5 |
周五 | 0 | 2 | 0.5 | 0 | 2.5 |
周六 | 0 | 3 | 0 | 0 | 3 |
周日 | |||||
周总计 | 4 | 9.5 | 2 | 2 | 17.5 |
时间记录日志(单位:min):
日期 | 开始时间 | 结束时间 | 中断时间 | 净时间 | 活动 | 备注 |
星期一 | 14:00 | 15:50 | 10(课间) | 100 | 听课 | 软件工程上课 |
19:30 | 21:30 | 30 | 90 | 阅读、上网查资料 | ||
星期二 | 19:30 | 21:30 | 30 | 90 | 编程、阅读 | |
星期三 | 14:00 | 15:00 | 0 | 60 | 编程 | 数组最大子数组之和 |
19:00 | 20:30 | 30 | 120 | 编程 | ||
星期四 | 14:00 | 15:50 | 10(课间) | 100 | 听课 | 软件工程上课 |
16:20 | 17:30 | 0 | 70 | 编程、上网查资料 | 数组最大子数组之和2的程序 | |
19:30 | 21:00 | 30 | 60 | 编程 | 数组最大子数组之和2的程序 | |
星期五 | 14:00 | 17:00 | 60 | 120 | 编程 | 数组最大子数组之和2的程序 |
星期六 | 8:00 | 11:30 | 30(洗漱) | 180 | 修改,调试,发布 | 数组最大子数组之和程序进行修改、调试、写博客并发布 |