最大子序列和的问题

来源:互联网 发布:众筹网络大电影 编辑:程序博客网 时间:2024/06/11 21:28
<span style="font-family: SimSun; background-color: rgb(255, 255, 255);">最大子序列和的问题</span>
   需求:给定一列数据,要求找到该序列中最大的子序列和的值是多少?
    要求:详细描述自己的思路,并给出算法分析,最后写程序实现该程序.
    思路:如果用以前学过的知识,可以用穷举法来描述出该问题,或者是稍加分析,用两层for循环嵌套来实现也可以。第一种穷举法的时间复杂度是O(N^3),效率最差;第二种方法的时间复杂度为O(N^2).
    学习了算法之后,考虑用新的思路来解决该问题,分治策略.
    所谓分治策略,其实就是考虑把大问题分成两个大致相等的子问题,然后递归地对他们求解,这是"分"的部分."治"阶段将两个子问题的解修补到一起并可能再做些少量的附加工作,最后得到整个问题的解.
    1、用分治策略思想来考虑最大子序列和的问题:
给出一个组序列.若要找出最大子序列和的值,可以考虑将大的序列分成左右两个数据个数大致相等的子序列.则最大子序列要么在左边子序列中,要么在右边子序列中,要么是左边子序列的一部分(包含左边子序列的最后一个元素)和右边子序列的一部分(包含右边子序列的第一个元素)的和.要求的最大子序列和的值肯定是这三种情况中的一种.接下来的问题就是将上面讲的三种情况的值都算出来,三个值里面找最大的就好了.如何找左边子序列的最大值和右边子序列的最大值呢?可以用递归的方式来解决这个问题.
    总结:通过分析,分治算法的时间复杂度为O(NlogN),效率有了明显提高.
代码如下:
class MaxSubSumTest{public static void main(String [] args){int [] a = { 4, -3, 5, -2, -1, 2, 6, -2};int maxSum = maxSumRec(a,0,a.length-1);System.out.println(maxSum);System.out.println("Hello World");}//分治算法的实现public static int maxSumRec(int [] a,int left, int right){if(left==right)if(a[left]>0)return a[left];elsereturn 0;int center  = (left+right)/2;//左边子序列的最大值int maxLeftSum = maxSumRec(a,left,center);//右边子序列的最大值int maxRightSum = maxSumRec(a,center+1,right);//左边子序列的部分最大值(包含左边最后一个元素)int maxLeftBorderSum = 0;//包含左边界的最大值int leftBorderSum = 0;for(int i = center; i>=left; i--){leftBorderSum += a[i];if(leftBorderSum>maxLeftBorderSum){maxLeftBorderSum = leftBorderSum;}}//右边子序列的部分最大值(包含右边第一个元素)int maxRightBorderSum = 0;int rightBorderSum = 0;for(int i = center+1; i <= right; i++){rightBorderSum += a[i];if(rightBorderSum > maxRightBorderSum){maxRightBorderSum = rightBorderSum;}}return max(maxLeftSum,maxRightSum,maxLeftBorderSum+maxRightBorderSum);}//三个数值中的最大值public static int max(int left,int right, int mindle){int max = left > right ? left:right;max = max > mindle ? max : mindle;return max;}}
    其实还有第四中方法就是,采用动态规划的思想来解答
    2、采用动态规划的算法来考虑最大子序列和的问题:其时间复杂度是O(N)
动态规划的过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最有化解决问题的过程就称之为动态规划.其基本思想与分治法相似,也是将待求解问题分解为若干个子问题,按顺序求解子问题,前一个问题的解为后一个问题的求解提供了有用的信息.在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解.依次解决各子问题,最后一个子问题就是初始问题的解.与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解).能采用动态规划求解的问题一般具有三个性质:
1).最优化原理.如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构即满足最优化原理.
2).无后效性.即某阶段状态一旦确定,就不受整个状态以后决策的影响.也就是说,某状态以后的过程不会影响以前的状态.只与当前状态有关.
3).有重叠子问题.即子问题之间是不独立的,一个子问题在下一个阶段决策中可能被多次使用到(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)
int max_sub2(int a[], int size)  
{   
int i,max=0,temp_sum=0;   
for(i=0;i<size;i++)   
{       
temp_sum+=a[i];       
if(temp_sum>max)         
max=temp_sum;       
else if(temp_sum<0)         
temp_sum=0;   
}   return max;  
}
0 0
原创粉丝点击