最大子数问题

来源:互联网 发布:贵阳大数据是传销吗 编辑:程序博客网 时间:2024/06/05 17:39

本文题目在《算法导论》第38页(主要是写题目好麻烦)


通过观察图4-1,我们会发现:要想使收益最大化,那么就要选择价格变化最大的两天。而所谓的价格变化,实际上是两者之间差的绝对值得变化。


因此我们可以化简这个问题(这一步很重要,它反映了问题的本质,从而解决一类问题)


所以,图4-1就可以简化为             1     2     3    4     5     6    7    8      9     10     11     12     13      14     15     16     (天数)

                                                 13  -3   -25  20  -3  -16  -23  18  20    -7     12      -5     -22     15      -4       7     (价格变化)


此时你可以看到:应该在第8天买入,第11天卖出。


要想写出一个好的算法,首先要做的是从所给的例子中发现规律(就跟数学证明一样)


在这个题中,我们可以看出。要想做到收益最大化。应该满足下面几个条件:


1、这个非空连续子数组中,每个数相加,所得的总和应该是全部数组中最大的。


2、在这个数组中,负数实际上对总和没用(起作用的是非零的正整数)。


3、这个数组的开头和结尾的位置都应该为正整数。


4、这个非空连续子数组有三种范围(数组A【low,mid]):   low<=i<=j<=mid、low<i<=j<=mid、low<i<=j<mid    //这也是缩小范围的一种方式,总之区分过程越简单越好

//在这里,犯了一个错误,想把查找范围缩小,以为可以通过减小范围来减少运算量,从每个正整数开始,到下一个正整数为止(实际上,这个划分范围就比较麻烦了,反而增大了编程过程)

——————————————————————————————————————这个代码是大神写的(我们不生产代码,我们只是代码的搬运工)

/*最优方法,时间复杂度O(n)和最大的子序列的第一个元素肯定是正数因为元素有正有负,因此子序列的最大和一定大于0*/int MaxSubSum3(int *arr,int len){int i;int MaxSum = 0;int CurSum = 0;for(i=0;i<len;i++){CurSum += arr[i];if(CurSum > MaxSum)MaxSum = CurSum;//如果累加和出现小于0的情况,//则和最大的子序列肯定不可能包含前面的元素,//这时将累加和置0,从下个元素重新开始累加if(CurSum < 0)CurSum = 0;}return MaxSum;}


上面的这个代码仔细想了想,发现它把整个数组分成三部分(有些情况下是两部分)  //这才是减小范围,从而减小运算量


把整个数组里的元素加一遍,通过找出最大的连续数组前面的不符合条件方法,确定出最后结果。








 

0 0