“练习的时候,不要害怕出错,错误越多,你得到的经验就会越多,理解的就越深刻。” by Y
题目要求:数组成环,输入一个数组,输出最大连续子数组和以及其的区间下标。
一、项目实践总结
算法设计:
最大连续数组和算是一个小的dp问题,只需要理解状态转移方程---dp[ i ] = max( dp[ i -1 ] ) + arr[ i ] ,arr[ i ] ) (dp[i]为以i为结尾的最大连续区间和) 此放大的时间复杂度为O(n) 。在本次作业中,不考虑时间复杂度的问题,所以不需要用dp法。题目要求数组成环,故而可以用下标(i + 1) % n 来形成循环,存储下标的时候注意每次更新最大值时修改右端点即可。
编码:
这次作业采用java语言编程,面向过程的思想有点严重,加上对于java语言掌握能力不是很高,所以敲起来耗时有点长。基于面向对象,我便将运算求取最大连续子数组和部分写了一个类,让这个类可以有方法求解,然后再main.java里面直接调用即可。
贴一下代码:
package com.company;
import java.util.ArrayList;
public class MaxArr {
static class MaxSumPosition{
int sum;
int l;
int r;
}
public static MaxSumPosition getResult(ArrayList<Integer> array,MaxSumPosition maxSumPosition) {
int ans = 0;
maxSumPosition.sum = array.get(0);
for(int i=0; i< array.size(); i++) {
if(ans <= 0) {
ans = array.get(i);
maxSumPosition.l = maxSumPosition.r = i;
}else {
ans += array.get(i);
}
if(ans > maxSumPosition.sum) {
maxSumPosition.sum = ans;
maxSumPosition.r = i;
}
}
return maxSumPosition;
}
public MaxSumPosition Getmax(int array[],int n) {
MaxSumPosition maxSumPosition = new MaxSumPosition();
int maxx = Integer.MIN_VALUE;
maxSumPosition.l = 0;
maxSumPosition.r = 0;
for(int i = 0; i < n; i ++) {
ArrayList<Integer> list = new ArrayList<>();
for(int j = i; ( j + 1 ) % n != i; j = (j + 1) % n) {
list.add(array[j]);
}
MaxSumPosition maxSumPosition1 = new MaxSumPosition();
maxSumPosition1 = getResult(list,maxSumPosition1);
if(maxSumPosition.sum < maxSumPosition1.sum) {
maxSumPosition.sum = maxSumPosition1.sum;
maxSumPosition.l = ( maxSumPosition1.l + i ) % n;
maxSumPosition.r = ( maxSumPosition1.r + i ) % n;
}
}
return maxSumPosition;
}
}
单元测试:
本程序中,我对我的Getmax方法进行测试,利用junit创建测试类。在书写测试类时少了@org.junit.Test,在回头检查时发现。由于自己对单元测试掌握不熟练,在创建的时候,多次回顾课内知识,出了很多次错,现在已经基本掌握了单元测试。
贴一下代码:
package com.company;
import org.junit.Assert;
import static org.junit.Assert.*;
public class MaxArr_GetmaxTest {
@org.junit.Test
public void Getmax(){
int n = 5;
int l=0,r=0;
int[] array = {2,1,12,-25,54};
MaxArr maxarr = new MaxArr();
MaxArr.MaxSumPosition maxSumPosition = maxarr.Getmax(array,n);
Assert.assertEquals(69,maxSumPosition.sum);
Assert.assertEquals(4,maxSumPosition.l);
Assert.assertEquals(2,maxSumPosition.r);
}
}
所用时间:
时间估计相差不多。程序设计,代码实现用时较短,单元测试部分耗时较长,主要还是自己当时初次了解单元测试,运用的不熟练。总体完成本次项目耗时差不多半天多,很不错了。
二、问题及解决方法
问题1:单元测试时语句覆盖率最开始没有达到100%,Main.java没用到,但是被包含到测试运行中了。
解决方法:将Main.java移除项目。
问题2:单元测试最初创建没跑成功。
解决方法:本次项目我是重新开了一个项目文件,但是没有先导入junit测试就直接进行测试,所以我重新看了一遍测试步骤,主要还是当时没理解。
三、认知变化
1.测试技能认知加深。
以往的程序设计,出测试样例用眼看,找特殊值、特殊情况,本次作业的测试用例不仅要答案正确,还需要满足单元测试的语句覆盖率达到100%。不仅如此,为了方便测试,也就是符合面向对象的语言书写,我将计算最大连续子数组和部分的代码放到了一个类里面,主函数直接调用类的方法,不然也不好写测试类。
四、心得体会
最大连续数组和算法思想起来不算困难,但对于java掌握一般,语句实现还是踩了点坑,加上对测试的掌握不是很熟练,整体来说耗时有点长。之前都是程序设计,仅仅是算法设计部分。即便是对程序进行测试,也是debug一下,出数据测试也是找特殊值判断这个程序对不对,不会想到语句覆盖、判定覆盖、条件覆盖、判定组合覆盖等等。这次作业,让我对软件测试的理解加深,掌握了如何用junit进行单元测试,如何设计符合要求的测试用例。