题目: 返回一个整数数组中最大子数组的和。
要求:
(1) 输入一个整形数组,数组里有正数也有负数。
(2)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
(3)如果数组A[0]……A[j-1]首尾相邻,允许A[i-1],…… A[n-1],A[0]……A[j-1]之和最大。
(4)同时返回最大子数组的位置。
(5)求所有子数组的和的最大值。
设计思路:
(1)此题和第一次求数组的最大子数组相比,是把第一次求得数组首尾相接形成环,求此环的最大子数组。
(2)要正确理解题意,求得的子数组的个数不能超过这个环形数组中的数的个数。由题意可设计如下方法:将原始输入的数组复制一份,将复制的数组放在初始数组的后边,并限定最大子数组的个数不能超过初始数组的个数(例:初始输入数组为{1 2 -4 5 6},则变换后的数组为{1 2 -4 5 6 ,1 2 -4 5 6})。
(3)这样,就将一个循环数组转换为一个顺序数组,求得此变换后的顺序数组的最大子数组(个数不超过初始数组的个数),求得的最大子数组即为形成的环形数组的最大子数组。
//本程序实现的功能是:将一个数组首尾相接连成环,寻找环中的最大子数组 //2016.3.26 #include<iostream> #include<string> #define MAX 200 using namespace std; void InPutArray(int intArray[],int &intNum) { cout << "请输入一个整数数组(数组个数不超过100):" << endl; for (int i = 0; i < 100; i++) { if (cin.peek() == 10) { cin.clear(); break; } cin >> intArray[i]; intNum++; } } void GetMaxSonArray(int intArray[],int &intPre,int &intAfter,int intDblNum) { int intSum = -65535; int intCurSum=0; int intSegment; int intResult[MAX][MAX]; int intX; int intY; intX = 0; intY = 0; intSegment = 0; intPre = 0; //初始化最大子数组的第一个数的位置为0 int intDistance=0; //最大子数组第一个数和最后一个数的距离 int intSignalNum; intSignalNum = intDblNum / 2; for (int i = 0; i < intDblNum; i++) { intCurSum = intCurSum + intArray[i]; intDistance = intAfter - intPre + 2; //此处应该为加2,不能加1 cout << "intDistance=" << intDistance <<" "<< "intSignalNum=" << intSignalNum << endl; if (intDistance == intSignalNum) { intResult[intX][intY] = intPre; intResult[intX][intY + 1] = intAfter; intResult[intX][intY + 2] = intSum; intX = intX + 1; intCurSum = intCurSum - intArray[intPre]; intPre = intPre + 1; } if (intCurSum>intSum) { intSum = intCurSum; intAfter = i; } if (intCurSum < 0) { intResult[intX][intY] = intPre; intResult[intX][intY + 1] = intAfter; intResult[intX][intY + 2] = intSum; intX = intX + 1; intSegment = intSegment + 1; intSum = 0; intCurSum = 0; intPre = i + 1; intAfter = 0; } cout << "intPre=" << intPre << " " << "intAfter=" << intAfter << endl; cout << "intSum=" << intSum << " " << "intCurSum=" << intCurSum << endl; } intResult[intX][intY] = intPre; intResult[intX][intY + 1] = intAfter; intResult[intX][intY + 2] = intSum; intSegment = intSegment + 1; int intLocation = 0; //记录最大子数组的位置 int max; max = intResult[0][2]; for (int i = 0; i < intSegment; i++) { if (intResult[i][2]>max) { max = intResult[i][2]; intLocation = i; } } intPre = intResult[intLocation][0]; intAfter = intResult[intLocation][1]; } int main() { int intNum=0; //此处开始没有初始化,导致调用函数时出错,不能返回数组 int intArray[MAX]; int intPre=0; int intAfter=0; int intSum=0; InPutArray(intArray, intNum); //扩展数组。方法:复制输入的数组,将其放在输入的数组的后边,这样就可以看成是一个环形数组了 int intDblNum = 2 * intNum; int j = 0; for (int i = intNum; i < intDblNum; i++) { intArray[i] = intArray[j]; j = j + 1; } GetMaxSonArray(intArray, intPre, intAfter, intDblNum); cout << "最大的子数组为:" << endl; for (int i = intPre; i <= intAfter; i++) { cout << intArray[i] << " "; intSum = intSum + intArray[i]; } cout << endl; cout << "最大的子数组的和为:" << intSum << endl; return 0; }
实验截图:
测试是否能够判断最大子数组的个数不能超过初始输入数组的个数。
测试是否能够成环进行求解
判断最大
工作图片:
周活动记录日志:
日期任务 | 听课/时 | 编写程序/时 | 查阅资料/时 | 日总计/时 |
星期一 | 2 | 2 | 4 | |
星期二 | 2 | 2 | ||
星期三 | 2 | 2 | 4 | |
星期四 | 2 | 1 | 3 | |
星期五 | 4 | 4 | ||
星期六 | ||||
星期日 | 1 | 1 | ||
周总计 | 4 | 11 | 3 |
18 |
时间记录日志:
日期 | 开始时间 | 结束时间 | 中断时间 | 净时间/分 | 活动 | 备注 |
3/21 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程上课 |
19:00 | 21:00 | 60 | 编写程序 | 课堂练习作业 | ||
3/22 | 19:00 | 21:30 | 20 | 120 | 自习 | |
3/23 | 14:30 | 18:00 | 15 | 自习 | ||
19:00 | 22::00 | 180 | 编写程序 | 作业 | ||
3/24 | 14:00 | 15:50 | 10 | 100 | 上课 | 软件工程上课 |
20:00 | 22:10 | 10 | 120 | 查资料,分析程序 | 课堂练习作业 | |
3/25 | 16:20 | 18:30 | 10 | 120 | 编程 | |
19:10 | 21:45 | 145 | 查阅资料+编程 |
缺陷日志:
日期 | 编号 | 缺陷内容 | 引入阶段 | 排除阶段 | 修复时间 | 修复缺陷 |
3月21日 | 1 |
调用函数时出错,不能返回参数 |
执行阶段 | 将功能加入到主函数中进行对比分析,调试时发现错误 | 10+ |
变量未初始化,导致调用函数时无法返回参数,所以初始化变量 |
3月25日 | 2 |
计算循环数组的最大子数组时,最大子数组个数超出初始数组的个数 |
执行阶段 | 通过设置相关参数的输出,进行分析判断 | 20+ |
判断时的条件出错,导致此功能未实现,修改完善判断条件 |
合作者:贾兆款、宋海林(http://www.cnblogs.com/hulidanxiang/p/5322705.html)