2021春-软工#1:数组中最大的子数组之和
一、目的
- 熟悉编程风格
- 实现简单单元测试
- 简单的性能分析
二、编程
1、程序分析
函数方法:主函数(Main)、实现最大子数组求和函数(calculate)
主函数:实现数组的长度以及数据的输入,输出最大子数组的和。
Calculate函数:实现求和过程
2、代码解读及运行结果
以下代码为数据的输入
1 Scanner sc = new Scanner(System.in);//定义输入对象 2 int n = sc.nextInt();//输入单个数据 3 int[] ary = new int[n]; 4 int[] ans = new int[n]; 5 for(int i = 0;i < n;i++){ 6 ary[i] = sc.nextInt(); 7 ans[i] = ary[i]; 8 } 9 sc.close();
实现求和的过程:
1、判断是否为全为负数的数组,使用sort进行排序,判断其最大值,小于等于0则输出其最大值,大于0另作运算
2、其数组最大值大于0时,将其最大子数组存入动态数组lst中,其和放在末尾
1 public static List<Integer> calculate(int ary[],int n,int[] ans){ 2 List<Integer> lst = new ArrayList<Integer>(); 3 int res = 0; 4 int temp = 0; 5 Arrays.sort(ary); 6 if(ary[ary.length-1] <= 0){ 7 lst.add(ary[ary.length-1]);//添加最大子数组 8 lst.add(ary[ary.length-1]);//添加最大子数组的和,由于全为负数,因此只有一个值时是最大的 9 } 10 else{ 11 for(int i = 0;i < ans.length;i++){ 12 temp += ans[i]; 13 if(temp < 0){ 14 temp = 0; 15 lst = new ArrayList<Integer>(); 16 continue; 17 }else if(res < temp){ 18 res = temp; 19 } 20 lst.add(ans[i]); 21 } 22 lst.add(res); 23 } 24 return lst; 25 }
实现输出其开始及结束下标:
获取其下标依次放入动态数组的末尾
1 public static List<Integer> add(int n,List<Integer> res,int[] ary){ 2 for(int i = 0;i < n;i++){ 3 if(ary[i] == res.get(0)) //获取其开始下标 4 res.add(i); 5 if(ary[i] == res.get(res.size()-3)){ //获取其结束下标 6 res.add(i); 7 break; 8 } 9 else continue; 10 } 11 return res; 12 }
3、单元测试
这里使用的是Junit的的单元测试工具。
配置过程
右键项目--> Bulid Path --> Config bulid path --> 右半部分Libraries --> Add Libraries --> 双击JUnit --> 选择JUnit 4 --> Finish
创建测试文件
右键项目包 --> new --> JUnit text Case -->输入文件名 --> Finish
实现过程:
定义输入数组,数组长度,
调用原方法,
判断结果是否正确
测试代码:
1 private Pritice pc; 2 @Test 3 public void test() { 4 int n = 4; 5 int[] ary = {-1,-2,-3,-4}; 6 int[] ans = {-1,-2,-3,-4}; 7 List<Integer> lst = pc.calculate(ary, n,ans);//原方法的调用 8 int s = lst.get(lst.size()-1); 9 assertEquals(s , -1);//比对输出与正确结果,看起是否正确 10 List<Integer> res = pc.add(n, lst, ans); 11 int x = lst.get(lst.size()-2); 12 int y = lst.get(lst.size()-1); 13 assertEquals(x , 0);//比对输出与正确结果,检查是否正确 14 assertEquals(y , 0); 15 } 16 @Test 17 public void test1() { 18 int n = 17; 19 int[] ary = {-32, -10, 33, -23, 32, -12, 41, -12, 1, 3, 5, -98, 70, -21, 10, -9, 61}; 20 int[] ans = {-32, -10, 33, -23, 32, -12, 41, -12, 1, 3, 5, -98, 70, -21, 10, -9, 61}; 21 List<Integer> lst = pc.calculate(ary, n,ans); 22 int s = lst.get(lst.size()-1); 23 assertEquals(s , 111); 24 List<Integer> res = pc.add(n, lst, ans); 25 int x = lst.get(lst.size()-2); 26 int y = lst.get(lst.size()-1); 27 assertEquals(x , 12); 28 assertEquals(y , 16); 29 }
测试结果:

三、性能分析结果及改进
1、性能分析
使用工具:JProfilter
JProfilter简介:
JProfiler是一个全功能的Java剖析工具(profiler),主要用于检查和跟踪系统(限于Java 开发的)的性能。JProfiler可以通过时时的监控系统的内存使用情况,随时监视垃圾回收,线程运行状况等手段,从而很好的监视JVM运行情况及其性能。它把CPU、线程和内存的剖析组合在一个强大的应用中。JProfiler可提供许多IDE整合和应用服务器整合功能。
代码的基础性能,如下图所示:

- 内存的使用占比较小,空闲的空间比较大,代码中的数组空间利用率不高。
- 外部依赖对象较多,数组所占总数的1/3
Live momery (内存视图)
所有记录对象的内存试图:

Heap walker (堆遍历)
堆的分配(方法中的累计分配树的分配):

CPU views(cpu视图)
调用图:

2、改进方法
1、改进在进行数组排序时的方法,降低其时间复杂度
2、使用动态数组存储数据,提高空间的利用效率

浙公网安备 33010602011771号