一、作业题目描述
最大连续子数组和: 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n
例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。二、 题目分析
该题目给的要求是求数组的最大子数列和。
对于最大子数列和的问题,在时间复杂度为O(n)的情况下,求解时考虑两个基本事实: 事实1: 对于一个从头开始的子数列,如果这个数列的和小于0,那么这个子数列不可能在所要求的最大子数列里。 事实2: 对于一个首尾随机的有序数列,数列和为正向扫描的当前最大的子数列,如果加上下一个数后,数列的和小于0了,那么原数列加上后一个数从而组成的数列就不会是最大连续子数列。此时应该保持原数列的和的值,再向后寻找的时候需要将下一个数作为查找的子数列的首项。 依照此想法,可获得下面的求解方法: 将数列从头到尾依次扫描,逐次相加。每次相加的时候查看加和是否比已知的最大连续子数列和大。如果较大,则替换最大和,否则,查看加和是否为负数。如果为负数,则保留之前的最大和,同时将先前的数列清空,从下一个数开始重新相加,比较最大值。三、流程图和实现代码
3.1 流程图
流程图如下:
![1649296-20190420161055879-748196386.png](https://img2018.cnblogs.com/blog/1649296/201904/1649296-20190420161055879-748196386.png)
3.2 具体代码
根据流程图可编写出具体代码。
对该算法的代码如下:public int GetMax() { int MaxNow = 0; int NumNow = 0; if(n < 0) { return -1; } for(int i = 0 ;i < n ;i++) { NumNow += NumList[i]; if(NumNow > MaxNow) { MaxNow = NumNow; } else if( NumNow < 0) { NumNow = 0; } } return MaxNow; }
可执行的代码地址:
四、单元测试
4.1测试覆盖方式选择以及判断分析
选择条件组合覆盖方式。
由流程图可知,该流程主要的判断有四个: 1.对n的判断: n<0; n>=0;2.对i的判断:
i<n; i>=n;3.对NumNow是否大于MaxNow的判断:
NumNow>MaxNow; NumNow<MaxNow;4.对NumNow是否小于0的判断:
NumNow>0; NumNow<0;由于2中对i的判断是在循环中进行的,而且是在n>0的情况下必然发生的事情,所以可以归类为对n的判断。
在3和4中的对NumNow的判断,可以整合为对NumNow>MaxNow、0<=NumNow<=MaxNow、NumNow<0三种情况判断。而且因为该判断处在循环中,所以有一起发生的可能。4.2 条件组合覆盖方式的可能组合
所有可能的组合为:
1.n<0; 2.n=0; 3.n>0;NumNow>MaxNow; 4.n>0;NumNow>MaxNow;0<=NumNow<=MaxNow; 5.n>0;NumNow<0; 6.n>0;NumNow>MaxNow;0<=NumNow<=MaxNow;NumNow<0; 7.n>0;0<=NumNow<=MaxNow; 8.n>0;0<=NumNow<=MaxNow;NumNow<0; 9.n>0;NumNow>MaxNow;NumNow<0;4.3依据测试组合设计样例
所以设计测试样例为:
- n=6,数列为:-1,-2,-3,-4,-5,-6; 满足组合:5;
- n=6,数列为:-2,11,-4,13,-5,-2; 满足组合:6;
- n=0,数列为:空; 满足组合:2;
- n=-1,数列为:空; 满足组合:1;
- n=6,数列为:1,2,4,5,6,7; 满足组合:3;
- n=6,数列为:11,11,-4,-1,-1,-1; 满足组合:4;
- n=6,数列为:0,0,0,0,0,0; 满足组合:7;
- n=6,数列为:0,-1,-4,-5,-5,-2; 满足组合:8;
n=6,数列为:-1,3,-4,-5,-5,-2;
满足组合:9;4.4测试代码
测试代码如下:
package homework;import static org.junit.jupiter.api.Assertions.*;import org.junit.jupiter.api.Test;class NumListTest { @Test void testGetMax1() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {-1,-2,-3,-4,-5,-6}; assertEquals(0,a.GetMax()); } @Test void testGetMax2() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {-2,11,-4,13,-5,-2}; assertEquals(20,a.GetMax()); } @Test void testGetMax3() { NumList a = new NumList(); a.n = 0; a.NumList =new int[] {}; assertEquals(0,a.GetMax()); } @Test void testGetMax4() { NumList a = new NumList(); a.n = -1; a.NumList =new int[] {}; assertEquals(-1,a.GetMax()); } @Test void testGetMax5() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {1,3,4,5,6,7}; assertEquals(26,a.GetMax()); } @Test void testGetMax6() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {11,11,-4,-1,-1,-1}; assertEquals(22,a.GetMax()); } @Test void testGetMax7() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {0,0,0,0,0,0}; assertEquals(0,a.GetMax()); } @Test void testGetMax8() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {0,-1,-4,-5,-5,-2}; assertEquals(0,a.GetMax()); } @Test void testGetMax9() { NumList a = new NumList(); a.n = 6; a.NumList =new int[] {-1,3,-4,-5,-5,-2}; assertEquals(3,a.GetMax()); }}
测试代码地址
4.5测试结果:
测试截图如下:
![1649296-20190420171935363-1303252294.png](https://img2018.cnblogs.com/blog/1649296/201904/1649296-20190420171935363-1303252294.png)