软件工程(2019)第三次作业
一、作业题目描述
最大连续子数组和: 给定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 流程图
流程图如下:
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;
}
可执行的代码地址:github代码
四、单元测试
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());
}
}
测试代码地址github代码_测试
4.5测试结果:
测试截图如下: