二维数组中最大连通子数组之和

一、目的

  1. 熟悉编程风格
  2. 实现简单单元测试
  3. 简单的性能分析
  4. 在上次的最大子数组上实现进阶,求最大连通子数组

二、编程

1、程序分析

所用函数:

主函数(Main)

最大子数组函数(array)

判断是否存在其他字符函数(用于输出错误(isnum))、是否不为纯数字

文件读取函数(SparseArrayFromFile)

读取文件时是否存在其他字符(isnumber)

2、代码解读以及运行结果

2.1、代码解读

文件读取------SparseArrayFromFile()

 1     //为保存的数组分配空间
 2     public static int[][] datas;
 3     public static int[][] SparseArrayFromFile(String path){
 4         //将稀疏矩阵从文件中读取出来
 5         BufferedReader br = null;
 6         BufferedReader br1 = null;
 7         try {
 8             InputStreamReader isr = new InputStreamReader(new FileInputStream(new File(path)));
 9             InputStreamReader isr1 = new InputStreamReader(new FileInputStream(new File(path)));
10             br = new BufferedReader(isr);
11             br1 = new BufferedReader(isr1);
12             String res = null;
13             int i = 1;
14             int n,s;
15             n = Integer.valueOf(br.readLine());//
16             s = Integer.valueOf(br.readLine());//
17             if(!isnumber(br1)){//判断是否存在非整数(*等符号)
18                 datas = new int[n+2][s+2];
19                 for (int x = 0;x < n+2;x++){
20                     for (int y = 0;y < s+2;y++){
21                         datas[x][y] = Integer.MAX_VALUE;
22                     }
23                 }
24             }else{
25                 //为保存的数组分配空间
26                 datas = new int[n+2][s+2];
27                 for(int x = 0;x < n+2;x++){
28                     for (int y = 0;y < s+2;y++){
29                         datas[x][y] = Integer.MIN_VALUE;
30                     }
31                 }
32                 //按行读取
33                 while(null != (res = br.readLine())) {
34                     if (null != res) {
35                         //按行读取的字符串按逗号分割,得到一个String数组
36                         String[] str = res.split(",");
37                         //依此转为int型存入分配好的空间数组中
38                         for (int k = 0; k < str.length; k++) {
39                             //判断是否是负数,将其后的数直接强转为整型
40                             if (str[k].charAt(0) == '-') {
41                                 String num = "";
42                                 for (int m = 1; m < str[k].length(); m++) {
43                                     num += str[k].charAt(m);
44                                 }
45                                 int snum = Integer.valueOf(num);
46                                 datas[i][k+1] = -snum;
47                             } else {//为正数时,直接强转为整型
48                                 datas[i][k+1] = Integer.valueOf(str[k]);
49                             }
50                         }
51                         i++;//行数加1
52                     }
53                 }
54             }
55             br.close();
56             isr.close();
57         } catch (Exception e) {
58             e.printStackTrace();
59         }
60         return datas;
61     }

判断其他字符------isnumber()

 

 1    //判断是否存储不为数字的其他字符
 2     public static boolean isnumber(BufferedReader br){
 3         boolean flag = true;
 4         String res = "";
 5         try{
 6             int n = Integer.valueOf(br.readLine());
 7             int s = Integer.valueOf(br.readLine());
 8             while(null != (res = br.readLine())){
 9                 if(res != null){
10                     //按行读取的字符串按逗号分割,得到一个String数组
11                     String[] str = res.split(",");
12                     for(int i = 0;i < str.length;i++){
13                         //判断是否存在字符,多个字符连接也可判断
14                         if(str[i].charAt(0) == '-'){
15                             for(int k = 1;k < str[i].length();k++){
16                                 if(str[i].charAt(k)-'0' < 10 && str[i].charAt(k)-'0' >= 0)
17                                     continue;
18                                 else{
19                                     flag = false;
20                                     break;
21                                 }
22                             }
23                         }else{
24                             for(int k = 0;k < str[i].length();k++){
25                                 if(str[i].charAt(k)-'0' < 10 && str[i].charAt(k)-'0' >= 0)
26                                     continue;
27                                 else{
28                                     flag = false;
29                                     break;
30                                 }
31                             }
32                         }
33                         if (!flag)
34                             break;
35                     }
36                     if (!flag)
37                         break;
38                 }
39             }
40             br.close();
41         }catch (Exception e){
42             e.printStackTrace();
43         }
44         return flag;
45     }

主函数------Main()

 1   public static void main(String[] args) {
 2         FileRead fd = new FileRead();
 3         int[][] datas = fd.SparseArrayFromFile("D:\\IDEA\\Workspaces\\MaxArray\\data\\3.txt");
 4         int res = Integer.MIN_VALUE;
 5         if (!isnum(datas)){
 6             System.out.println("字符存储错误");
 7         }else {
 8             int[][] ary = new int[datas.length][datas[0].length];
 9             for (int i = 1; i < datas.length - 1; i++) {//
10                 for (int j = 1; j < datas[0].length - 1; j++) {//
11                     ary = memset(datas, ary);
12                     res = Math.max(res, array(i, j, ary, Integer.MIN_VALUE));
13                 }
14             }
15             System.out.println(res);
16         }
17     }

求最大子数组------array()

算法思路:

找到第一个点,找其上、下、左、右四个方向中找最大值,然后将其变成最小值,然后存储器最大值,在移动时,发现其范围内的其他正数直接加入。

 1     //求最大子数组
 2     /**
 3      * 算法思路:
 4      *      找到每一个点的相邻点中的最大值(上、下、左、右),相加,存储最大值,加一位数,将其更替为最小值,防止回走
 5      * */
 6     public static int array(int x,int y,int[][] datas,int temp){
 7         int len = (datas.length-1)*(datas[0].length-1);
 8         int res = Integer.MIN_VALUE;
 9         temp = datas[x][y];
10         int m = x,n = y;
11         for(int i = 0;i < len;i++){
12             res = Math.max(res,temp);
13             datas[m][n] = Integer.MIN_VALUE;
14             if(datas[m-1][n] > datas[m+1][n] && datas[m-1][n] > datas[m][n+1] && datas[m-1][n] > datas[m][n-1]){//
15                 if(datas[m+1][n] > 0 && datas[m+1][n] != Integer.MIN_VALUE){
16                     temp += datas[m+1][n];
17                     datas[m+1][n] = Integer.MIN_VALUE;
18                 }else if(datas[m][n-1] > 0 && datas[m][n-1] != Integer.MIN_VALUE){
19                     temp += datas[m][n-1];
20                     datas[m][n-1] = Integer.MIN_VALUE;
21                 }else if(datas[m][n+1] > 0 && datas[m][n+1] != Integer.MIN_VALUE){
22                     temp += datas[m][n+1];
23                     datas[m][n+1] = Integer.MIN_VALUE;
24                 }
25                 temp += datas[m-1][n];
26                 m = m - 1;
27                 n = n;
28             }else if(datas[m+1][n] > datas[m-1][n] && datas[m+1][n] > datas[m][n-1] && datas[m+1][n] > datas[m][n+1]){//
29                 if(datas[m-1][n] > 0 && datas[m-1][n] != Integer.MIN_VALUE){
30                     temp += datas[m-1][n];
31                     datas[m-1][n] = Integer.MIN_VALUE;
32                 }else if(datas[m][n+1] > 0 && datas[m][n+1] != Integer.MIN_VALUE){
33                     temp += datas[m][n+1];
34                     datas[m][n+1] = Integer.MIN_VALUE;
35                 }else if(datas[m][n-1] > 0 && datas[m][n-1] != Integer.MIN_VALUE){
36                     temp += datas[m][n-1];
37                     datas[m][n-1] = Integer.MIN_VALUE;
38                 }
39                 temp += datas[m+1][n];
40                 m = m + 1;
41                 n = n;
42             }else if(datas[m][n-1] > datas[m+1][n] && datas[m][n-1] > datas[m-1][n] && datas[m][n-1] > datas[m][n+1]){//
43                 if(datas[m-1][n] > 0 && datas[m-1][n] != Integer.MIN_VALUE){
44                     temp += datas[m-1][n];
45                     datas[m-1][n] = Integer.MIN_VALUE;
46                 }else if(datas[m+1][n] > 0 && datas[m+1][n] != Integer.MIN_VALUE){
47                     temp += datas[m+1][n];
48                     datas[m+1][n] = Integer.MIN_VALUE;
49                 }else if(datas[m][n+1] > 0 && datas[m][n+1] != Integer.MIN_VALUE){
50                     temp += datas[m][n+1];
51                     datas[m][n+1] = Integer.MIN_VALUE;
52                 }
53                 temp += datas[m][n-1];
54                 m = m;
55                 n = n - 1;
56             }else if(datas[m][n+1] > datas[m+1][n] && datas[m][n+1] > datas[m-1][n] && datas[m][n+1] > datas[m][n-1]){//
57                 if(datas[m-1][n] > 0 && datas[m-1][n] != Integer.MIN_VALUE){
58                     temp += datas[m-1][n];
59                     datas[m-1][n] = Integer.MIN_VALUE;
60                 }else if(datas[m][n-1] > 0 && datas[m][n-1] != Integer.MIN_VALUE){
61                     temp += datas[m][n-1];
62                     datas[m][n-1] = Integer.MIN_VALUE;
63                 }else if(datas[m+1][n] > 0 && datas[m][n+1] != Integer.MIN_VALUE){
64                     temp += datas[m+1][n];
65                     datas[m+1][n] = Integer.MIN_VALUE;
66                 }
67                 temp += datas[m][n+1];
68                 m = m;
69                 n = n + 1;
70             }
71             datas[m][n] = Integer.MIN_VALUE;
72         }
73         return res;
74     }

判断输出错误值------isnum()

1     //判断数组是否存在其他字符
2     public static boolean isnum(int[][] datas){
3         boolean flag = true;
4         if(datas[0][0] == Integer.MAX_VALUE)
5             flag = false;
6         return flag;
7     }

2.2、结果展示

文件1

结果:

文件2

结果:

文件3

结果:

文件4

结果:

3、单元测试

这里使用了三个测试,结果如下

测试代码:

 1 public class MaxArrayTest extends MaxArray {
 2     private MaxArray ma;
 3     private FileRead fr;
 4     @Test
 5     public void array1() {
 6         int[][] datas = fr.SparseArrayFromFile("D:\\IDEA\\Workspaces\\MaxArray\\data\\1.txt");
 7         int res = Integer.MIN_VALUE;
 8         int[][] ary = new int[datas.length][datas[0].length];
 9         for(int i = 1;i < datas.length-1;i++){//
10             for(int j = 1;j < datas[0].length-1;j++){//
11                 ary = memset(datas,ary);
12                 res = Math.max(res,array(i,j,ary,Integer.MIN_VALUE));
13             }
14         }
15         assertEquals(res,-1);
16     }
17     @Test
18     public void array2() {
19         int[][] datas = fr.SparseArrayFromFile("D:\\IDEA\\Workspaces\\MaxArray\\data\\2.txt");
20         int res = Integer.MIN_VALUE;
21         int[][] ary = new int[datas.length][datas[0].length];
22         for(int i = 1;i < datas.length-1;i++){//
23             for(int j = 1;j < datas[0].length-1;j++){//
24                 ary = memset(datas,ary);
25                 res = Math.max(res,array(i,j,ary,Integer.MIN_VALUE));
26             }
27         }
28         assertEquals(res,23);
29     }
30     @Test
31     public void array3() {
32         int[][] datas = fr.SparseArrayFromFile("D:\\IDEA\\Workspaces\\MaxArray\\data\\3.txt");
33         assertEquals(isnum(datas),false);
34     }
35     @Test
36     public void array4() {
37         int[][] datas = fr.SparseArrayFromFile("D:\\IDEA\\Workspaces\\MaxArray\\data\\4.txt");
38         int res = Integer.MIN_VALUE;
39         int[][] ary = new int[datas.length][datas[0].length];
40         for(int i = 1;i < datas.length-1;i++){//
41             for(int j = 1;j < datas[0].length-1;j++){//
42                 ary = memset(datas,ary);
43                 res = Math.max(res,array(i,j,ary,Integer.MIN_VALUE));
44             }
45         }
46         assertEquals(res,25);
47     }
48 }

结果展示:

 三、性能分析结果及改进

1、性能分析

使用工具:JProfilter

JProfilter简介:

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

 代码基础性能,如下图所示:

 

内存的使用占比较小,空闲的空间比较大,代码中的数组空间利用率不高。

Live momery (内存视图)

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

CPU views(cpu视图)

调用图:

2、改进方法

  1. 使用动态数组存储数据,提高空间的利用效率
  2. 修改判断方法,提高代码执行效率。

 四、代码覆盖率

测试显示(由于IDEA覆盖率的显示只是显示在边缘,所以这里直接贴图,方便观看):

MaxArray函数代码覆盖率:

 

 

 FileRead函数覆盖率:

 

以上为所有代码的覆盖率显示,行号旁的绿色表示覆盖的代码,红色表示未覆盖的代码。

 

 

 

 

 

 

 

posted @ 2021-03-31 15:08  枫祈  阅读(118)  评论(3)    收藏  举报