《编程之美》读书笔记一

来源:互联网 发布:java字符串补零 编辑:程序博客网 时间:2024/05/19 03:17

  “给定一个含有N个整数的一维数组A[n],要求返回这个数组的子数组之和的最大值是什么。”刚看到这个题时,第一反应就是来两个for循环,咔嚓一下在O(n*n)时间内得到解,瞥了一眼下文,好像说的是还有O(n)和O(nlogn)的解法。想了好一会儿还是没有想到O(n)的解法怎么实现,O(nlogn)的解法倒是想到了:就是用分治法的思想来求解这个问题。将数组分成两部分,它的解一定是下main三种情况之一:和最大的在前半部分;和最大的在后半部分,和最大的跨过这两部分。前两种情况递归求解即可,第三种情况分别找出以A[n/2-1]结尾的前半部分和最大的子数组和以A[n/2]开始的后半部分的和最大的子数组,把两者相加即为原问题的解。(思想知道了,但代码没有实现)

  把O(nlogn)找到后,想了很久也没有找到O(n)的解法,就一不小心把答案看了,期基本思想就是在遍历数组的过程中,用两个变量分别保存当前已取得的最大值和接下来可能取得的最大值,然后比较两个取最大的。受此启发想出了另外一种编码方式,给出代码如下:

int     MaxSum(int *arry,int n)//n是数组的长度

{

    int     cur,sum=0;

    cut=arry[0];

    for(int i=1;i<n;i++)

    {

        cur = cur<0 ? arry[i] : cur + arry[i];

        if(sum<cur)

            sum=cur;

    }

    return   sum;

}

   我测试了一下这段代码貌似在C语言的int表示范围内都能得到正确解。

  扩展:(1)若要返回子数组的起始位置,只需在for循环中添加相应的代码即可(设置两个标志变量,让他们跟着sum变化),时间复杂度不变。(2)如果数组是循环数组的话的求解方案(循环数组即:最后一个元素的下一个元素是数组的起始元素):一个比较笨的办法就是申请一个长度为2N的数组0~n-1存储原数组,n~2n-1反向存储原数组,在上诉解法中稍作修改就可实现。另外一个相对好点的方法:这个问题可分为两种情况:a.A[n]没在解之列,即就是原问题;B、解的子数组含有A[n-1],这种情况就是寻找以A[n-1]结束的和最大的子数组和以A[0]开始的和最大的子数组,然后把两个相加得出最终解(要考虑特殊情况:当A[n]这个数组的元素全是正数时,注意条件判断)。

原创粉丝点击