• [软件工程学习笔记]结对作业---最大子数组问题


         今天的软件工程课老师让我们结对的小组现场来完成一个小程序。

          题目: 输入一个整型数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。

           我和永哥随即进入紧张的讨论,和大多数同学一样,很短的时间内谁也没有顾及时间复杂度的问题,首先要对每相邻的数组进行求和,然后再将求和的结果与max最大值进行比较,若大于则互换继续比较。在求和的问题上,我们将每个元素顺序跟后面相邻的元素相加,需要用到三个for循环,很短的时间内,我们一致同意用这个算法来解决,以便可以在当堂完成程序。

           大神就是大神,永哥编程从来不打草稿,只需灵机一动,一串代码就能浮现在他脑子里。我们的讨论在短短五分钟内就结束了,只上除了潦草的几个方块和曲线再也没有其他。永哥最擅长的语言是java,用起来收放自如得心应手,而在java上,我只算是个初学者,只能在一旁试图跟上他的节奏。

           他首先建了一个SumObject类:其中定义了和sum和数组下标indexs。

     1 package cn.stdu.edu.cn.domin;
     2 
     3 public class SumObject {
     4     private int sum;
     5     private String indexs;
     6     
     7     public SumObject(int sum,String indexs)
     8     {
     9         this.sum=sum;
    10         this.indexs=indexs;
    11     }
    12     public int getSum() {
    13         return sum;
    14     }
    15     public void setSum(int sum) {
    16         this.sum = sum;
    17     }
    18     public String getIndexs() {
    19         return indexs;
    20     }
    21     public void setIndexs(String indexs) {
    22         this.indexs = indexs;
    23     }
    24 }

    首先是一个求和的函数,具体的思路就是将每一个数都与剩下相邻的数进行求和,这样就用到了三个for循环语句。

     1 public void sum(int number[])
     2     {    
     3         int sum=0;
     4         String indexs="";
     5         for(int i=0;i<number.length;i++)
     6         {
     7             for(int j=0;j<number.length;j++)
     8             {
     9                 for(int n=i;n<=j;n++)
    10                 {
    11                     sum=sum+number[n];
    12                     indexs=indexs+n;
    13                 }
    14                 SumObject sumObject=new SumObject(sum,indexs);
    15                 sum=0;
    16                 indexs="";
    17                 sumList.add(sumObject);
    18             }
    19         }
    20     }

         二十分钟到了,我们的位置互换,接下来编写的任务就落在了我的头上,下面的任务就是对所求的和进行比较找出最大的进行输出,另外在java语句上的问题永哥对我也有一些指点,虽然在语言上并不熟悉,但还是顺利的完成了。

     1 public SumObject MaxOfSum()
     2     {
     3         int max=0;
     4         String indexs="";
     5         for(int i=0;i<sumList.size();i++)
     6         {
     7             if(max<sumList.get(i).getSum())
     8             {
     9                 max=sumList.get(i).getSum();
    10                 indexs=sumList.get(i).getIndexs();
    11             }
    12         }
    13         SumObject sumObject=new SumObject(max,indexs);
    14         return sumObject;
    15     }

    最后加入main函数检验我们的结果:

    1 public static void main(String[] args) {
    2         int num[]={-1,-2,3,60,-7,9,11,-32};
    3         SearchMaxSum searchMaxSum=new SearchMaxSum();
    4         searchMaxSum.sum(num);
    5         SumObject sumObject=searchMaxSum.MaxOfSum();
    6         System.out.println(sumObject.getSum()+"    "+sumObject.getIndexs());
    7     }

    运行结果:

    76    23456

    前面一项是最大和,后面一项是数组下标。

    ========================================

    以上是我们课堂上的过程,在课下我们对这道题的时间复杂度的问题上对算法再次进行了讨论。

    如果对第一个元素其到第n个元素的值是负数或零,则不必考虑其与后面的元素相加,直接将前面的和归零,从下一个元素开始再和后面的元素进行相加。反之继续相加得出最大值。这样我们就得到了一个复杂度为线性的算法。不必浪费时间去对每一种情况进行分析。机智的永哥以光速按照我们后来的思想写下了如下代码,简单粗暴,直接有效。

     1 /**  
     2     * @Name: bestSearchMaxSum
     3     * @Description: 在求子数组的最大和
     4     * @Author: 张永&吴盈盈
     5     * @Version: V1.00 
     6     * @Create Date: 2014-3-10 
     7     * @Parameters:整型数组number[],SumObject对象maxSumObject
     8     * @Return: SumObject对象
     9     */
    10     
    11     public SumObject bestSearchMaxSum(int number[], SumObject maxSumObject)   
    12     {  
    13         int i;  
    14         int max=0; 
    15         String indexStart=""; 
    16         String indexEnd="";
    17         for ( i = 0; i < number.length; i++ )  
    18         {  
    19             if ( (max= number[i] + max) > 0 )  
    20             {  
    21                 indexEnd = i+"";  
    22             }  
    23             else  
    24             {  
    25                 indexStart = ""+(i + 1);   
    26                 max = 0;  
    27             }  
    28             if ( max > maxSumObject.getSum() )   
    29             {  
    30                 maxSumObject.setSum(max);  
    31             }  
    32         }  
    33         maxSumObject.setIndexs(indexStart+indexEnd);
    34         return maxSumObject;
    35     }
    

    =================================

    我们本次课堂作业也算圆满的完成了。在这次作业的过程中突然想起前几日看老师给推荐的《人月神话》这本书上提到的一个经验法则:

    对软件任务的进度安排:

    1/3计划    1/6编码   1/4构建测试和早期系统测试   1/4系统测试,所有的构建已完成

    后两者对于我们来说还尚早。但前两者已经很能说明问题。

    在课上我们用五分钟来对算法进行计划,然后用四十分钟写出了一个时间复杂度较高的程序,显然这并不符合这个经验法则,对于我们来讲也是走了弯路浪费了更多的时间。急于求成往往会是丢了西瓜捡了芝麻。可能编码对于我来说还有很大的问题,但是这终究不是设计一个程序中最主要的问题所在,以后应当培养更加灵活的思维,给之后的工作做好万全的准备。

  • 相关阅读:
    Python os 方法指南
    网站后台500错误分析
    HTML中的meta标签常用属性及其作用总结
    Python线程理论
    python之struct详解
    python之路——初识面向对象
    configparser和hashlib模块
    logging模块
    re模块
    pickle,shelve,json模块
  • 原文地址:https://www.cnblogs.com/wingwyy511/p/3592527.html
Copyright © 2020-2023  润新知