软件工程(2018)第三次作业
最大连续子数组和
一.问题描述
给定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。
引用自《百度百科》
二.问题分析
已知一个sum数组,sum[i]表示第1个数到第i个数的和,于是sum[j] - sum[i-1]表示第i个数到第j个数的和。那么,以m为起点,n为终点最大子序列和为sum[n] - sum[m-1]。并且,sum[m]必然是sum[1],sum[2]...sum[n-1]中的最小值!如果在维护计算sum数组的时候,同时维护之前的最小值,答案就会迎刃而解。
程序代码:https://github.com/ZhangydA/CodeCollection
public class ContinuousMaximum {
public int continuousMaxinum(int arr[]){
int counter = 0;
for (int i = 0;i < arr.length;i ++){
if (arr[i] < 0) counter ++;
}
//如果所有的值都为负值,返回0
if (counter == arr.length) return 0;
int sum = 0,ans = Integer.MIN_VALUE,mins = 0;
for (int i = 0;i < arr.length;i ++){
sum += arr[i];
if (sum - mins > ans)
ans = sum - mins;
if (mins > sum)
mins = sum;
}
return ans;
}
}
测试类方法
import java.util.Scanner;
public class Test {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] arr = new int[n];
for (int i = 0;i < n;i ++){
arr[i] = input.nextInt();
}
System.out.println(new ContinuousMaximum().continuousMaxinum(arr));
input.close();
}
}
三.逻辑覆盖方法的比较
1.语句覆盖:语句覆盖是最起码的结构覆盖要求,语句覆盖要求设计足够多的测试用例,使得程序中每条语句至少被执行一次。
2.判定覆盖:判定覆盖又称为分支覆盖,它要求设计足够多的测试用例,使得程序中每个判定至少有一次为真值,有一次为假值。
3.条件覆盖:条件覆盖要求设计足够多的测试用例,使得判定中的每个条件获得各种可能的结果,即每个条件至少有一次为真值,有一次为假值。
4.条件/判定覆盖:设计足够多的测试用例,使得判定中每个条件的所有可能结果至少出现一次,每个判定本身所有可能结果也至少出现一次。
5.组合覆盖:要求设计足够多的测试用例,使得每个判定中条件结果的所有可能组合至少出现一次。 覆盖方法的优缺点及比较
四.组合覆盖
1.程序流程图
###2.选择分析测试样例及运行结果 通过流程图我们可知,组合覆盖一共有5中情况,分别是 B、ACE、ACF、ADE、ADF,经过了多次分析,选择了{-1,-2,-3,-4,-5}和{-2,5,-6,3,4}两组数据进行分析组合覆盖。 **第一组测试样例:** 样例运行结果 **第二组测试样例:** (1).样例运行结果 (2).数据路径覆盖分析数值 | sum | mins | ans | sum - mins > ans | mins > sum | 覆盖路径 |
---|---|---|---|---|---|---|
-2 | -2 | -oo | 0 | Y | Y | ACE |
5 | 3 | -2 | -2 | Y | N | ACF |
-6 | -3 | 5 | -2 | N | Y | ADE |
3 | 0 | 5 | -3 | N | N | ADF |
4 | 4 | 5 | - 3 | Y | N | ACF |
由上表可知,该组样例包含了ACE、ACF、ADE、ADF这四种情况,结合上述两组样例,覆盖了所有的情况,并且运行的结果与预期的结果一致。 |
3.JUnit自动测试
为了进一步的确任程序的正确性,接下来通过JUnit对多组数据进行自动测试,JUnit之参数化测试和成组测试的使用查看 这篇文章:
(1).JUnit自动测试类
package cn.sau.MaxSum;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class ContinuousMaximumAutoTest {
private int excepted;
private int[] array;
public ContinuousMaximumAutoTest(int excepted,int[] array){
this.excepted = excepted;
this.array = array;
}
/**
* 3.由@Parameterized.Parameters修饰一个
* public static Collection xxx()
*/
@Parameterized.Parameters
public static Collection data() {
return Arrays.asList(new Object[][] {
{ 20, new int[]{-2,11,-4,13,-5,-2}},
{ 7, new int[]{-2,5,-6,3,4}},//
{ 0, new int[]{-1,-2,-3,-4,-5}},
{ 12, new int[]{-1,6,-7,3,4,5,-6}}
});
}
@Test
public void test() {
assertEquals(excepted,new ContinuousMaximum().continuousMaxinum(array));
}
}
(2).测试类运行结果
五.总结
经过本次的作业,让我受益最大的有两点,第一点是学会了自己选择测试样例对自己的程序进行测试,第二点是学会了多组样例同时针对一个函数进行检测