一、题目及要求:
题目:返回一个整数数组中最大子数组的和
要求(新加):①如果数组A[0]...A[j-1]首尾相邻,允许A[i-1]...A[n-1],A[0]...A[j-1]之和最大;②同时返回最大子数组的位置。
二、设计思路:
我们要解决两个问题:求出环数组中最大的子数组;并且定位出该子数组的位置,把它们的名称输出来。要解决这两个问题,我们从以下两个方面入手:
①求出最大子数组:将数组数值按顺序排好称为“一趟”,每求出一趟的最大子数组后,将第一个数值放到最后一个,排成新的一趟,以此类推,直到遍历完成,求出最大环子数组。
②定位子数组:判断出当前求的和值为负数时,将之舍去,并将该数的下一个数的位置存起来作为最大子数组的头。当求出最大值后,该数的位置存起来作为子数组的尾。最后输出将子数组的名称。
三、源代码:
1 //结对开发—二 胡金辉 李青 2 3 #include "stdafx.h" 4 5 6 int _tmain(int argc, _TCHAR* argv[]) 7 { 8 int i,j,k,m,n,o,a[5]; 9 int Sum,Max,flag,flag1=0,flag2,flag4; 10 11 printf("请输入5个整数: "); 12 for(k=0;k<5;k++) 13 { 14 scanf("%d",&a[k]); 15 } 16 Max = a[0]; 17 for (m=0;m<5;m++) 18 { 19 for(i=0;i<5;i++) 20 { 21 Sum = 0; 22 for(j=i;j<5;j++) 23 { 24 Sum =Sum+ a[j]; 25 if(Sum<=0) 26 { 27 Sum=0; 28 flag1=(j+1+m)%5; 29 } 30 if(Sum > Max) 31 { 32 Max =Sum; 33 flag2=j+m; 34 } 35 } 36 } 37 flag=a[0]; 38 for(n=0;n<5;n++) 39 { 40 a[n]=a[n+1]; 41 } 42 a[4]=flag; 43 } 44 if(Sum==0) 45 { 46 47 Max=a[0]; 48 for(int e=0;e<5;e++) 49 { 50 if(a[e]>=Max) 51 { 52 Max=a[e]; 53 flag4=e; 54 } 55 } 56 57 } 58 printf("最大连续环子数组的和为:%d ",Max); 59 printf("该最大连续环子数组为:"); 60 61 if(Sum==0) 62 { 63 printf("a[%d]",flag4); 64 } 65 else 66 { 67 int flag3=flag2-flag1; 68 for(o=0;o<=flag3;o++) 69 { 70 printf("a[%d] ",flag1); 71 flag1++; 72 if(flag1>4) 73 flag1=0; 74 } 75 } 76 printf(" "); 77 return 0; 78 }
四、测试及运行结果:
测试数据:
3 6 -9 0 7(有正数、负数、零)
7 9 3 2 8 (只有正数)
-3 -6 -9 -2 -5(只有负数)
运行结果:
五、心得体会:
这个题目新加的要求是将这个一维数组看成是首尾相接的环,在求最大连续子数组时,还要考虑数组的尾部和头部的和是否也是正数并比之前的最大值还要大。我们在考虑这个问题时,首先想到的是用之前的算法接着进行计算,在原来的基本数组中求出最大的子数组,再考虑环的问题,但是我们发现,当这样求出来后,必须保证基本数组中求出来的最大子数组在最终的子数组当中,但是根据输入的数据不同,这种情况并不能保证,这种方法是行不通的。
值得一提的是,我们在解决定位子数组位置的过程中,遇到了困难。首先我们要定位子数组的头,想到的方法如下:因为每当和值为负,前面的值都舍去,不应再加到和当中,此时和为零,所以我们将下一个元素定为子数组的头。但是在定位子数组的尾时,由于输入的数据有正有负,并不能保证它在的位置,而且每一趟都可能会有更大的和值,所以我们在每确定一个最大值时,都定位一个尾,当和值最大时,就求出最终的尾部。
中间还有一个小插曲,就是如果输入的值全部为负值,那么和值为零,在解决这个问题时,我们单独将这种情况拿出来,如果符合这种情况的条件,就输出数组当中最大的值,并将它的名称输出来。
结对开发伙伴:李青 http://www.cnblogs.com/liqing1
工作照: