2021春-软工#1:数组中最大的子数组之和

一、目的

  1. 熟悉编程风格
  2. 实现简单单元测试
  3. 简单的性能分析

二、编程

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. 内存的使用占比较小,空闲的空间比较大,代码中的数组空间利用率不高。
  2. 外部依赖对象较多,数组所占总数的1/3

Live momery (内存视图)

所有记录对象的内存试图:

Heap walker (堆遍历)

堆的分配(方法中的累计分配树的分配):

CPU views(cpu视图)

调用图:

 

2、改进方法

1、改进在进行数组排序时的方法,降低其时间复杂度

2、使用动态数组存储数据,提高空间的利用效率

 

posted @ 2021-03-12 22:37  枫祈  阅读(130)  评论(1)    收藏  举报