现代程序设计 作业 第1次

  首先向老师表示歉意,由于误记了截止时间,作业提交迟到了3小时,十分抱歉。

  在第一周选课期间,我还没有决定选取该门课程,所以并未出席第一次课,也没有提交课堂作业。于是,我在同学的描述下得知了本次的题目。

  本次作业的题目是:最大子数组之和。即在一个数组中求得连续子串和的最大值。

  思考这个问题时,我首先想到的是动态规划。但是动态规划更适用于求子串位置的问题,本题目并不要求,所以可以有更简便的解法。如果使用穷举法,时间复杂度为O(n2),而使用动态规划,时间复杂度为O(nlogn)。虽然时间复杂度较小,但是递归算法的空间复杂度将会更高,这并不划算。所以我首选了穷举法来解决这个问题,关键代码如下:

    for (i=0;i<n;i++){ 
        for(j=i,ctemp=0;j<n;j++){
            ctemp+=t[j];
            if(ctemp>max)
                max=ctemp;
        }
    }

  这是一个简单的穷举法,从前到后穷举了每一个子串和,最终将最大值输出。

  不过这个程序还可以进一步改进。分析问题可以得知,具有最大和的子串的首尾元素不可能是负数。例如,如果是num[i]负数,则存在以num[i+1]为开头的更大子串。同理,以和为负的小子串开头的子串也必然是可以优化的。在网上查阅了一些资料后,我做出了以下优化:

    for (j=0; j<=i; j++){ 
        ctemp+=t[j]; 
        if (ctemp>max) 
            max=ctemp; 
        else if (ctemp<0) 
            ctemp=0; 
       }

  该段代码是在上一段基础之上的改进。其原理在于,通过排除负开头数字/子串的方式,节约了第一个for循环,从而将复杂度降低至O(n)的线性水平。

  不过此时也产生了一个例外情况:输入元素均为负值。那么还要增添一个判断条件,如果元素均为负,则最大子串和等于最大元素的值。

  以上为该次作业的全部讨论。

 

  另:我选择的教科书为 中文版 代码大全 (第二版)

posted on 2013-09-20 15:28  libcan  阅读(251)  评论(1编辑  收藏  举报