[分治递归]解决最大子序列和问题

简介:

Pnig0s1992 p.s:比较直白简单的嵌套for循环顺序累加判断的方式就不介绍了,比较容易实现,而且时间复杂度O(N^3) or O(N^2)比较坑爹。这里用分治递归的方法去解决O(NlogN),当然还有动态规划的方法O(N)以后再说。

先简单总结下分治递归的基本过程:

    1,传入待处理的序列集合,及初始下标(iLeft)和终点下标(iRight=N-1,N为元素个数)

    2,处理小容量问题 e.g:if(iLeft == iRight){....}

    3,将数据从中间分成两部分并将前后两部分依次递归调用。

    4,处理每个子段的过程。

核心部分注释的比较详细了,纯算法练习,高手飘过。

 

 
  1. //Code By Pnig0s1992  
  2. //Date:2012,3,12  
  3. #include <stdio.h>  
  4. #include <Windows.h>  
  5. #include <stdlib.h>  
  6.  
  7. #define N 8  
  8.  
  9. int CallSubsequenceSum(int s[],int iLength);  
  10. int SubsequenceSum(int s[],int iLeft,int iRight);  
  11. int Maxinthree(int a,int b,int c);  
  12.  
  13. int main(int argc,CHAR * argv[])  
  14. {  
  15.     int myList[N] = {4,-3,5,-2,-1,2,6,-2};  
  16.     int myResult;  
  17.     for(int i=0;i<N;i++)  
  18.     {  
  19.         printf("%d ",myList[i]);  
  20.     }  
  21.     myResult = CallSubsequenceSum(myList,N-1);  
  22.     printf("\n最大子序列和为:%d",myResult);  
  23.     system("pause");  
  24. }  
  25.  
  26. int CallSubsequenceSum(int s[],int iLength)  
  27. {  
  28.      return SubsequenceSum(s,0,iLength);  
  29. }  
  30.  
  31. int SubsequenceSum(int s[],int iLeft,int iRight)  
  32. {  
  33.     int iMaxLeftSum,iMaxRightSum; //表示  
  34.     int iRightBorderSum = 0,iLeftBorderSum = 0;  
  35.     int iMaxLeftBorderSum = 0,iMaxRightBorderSum = 0;  
  36.     int iCenter;  
  37.     if(iLeft == iRight) //解决小容量情况,当序列只有一个元素时,非负则返回唯一值,否则返回0(基准情况)  
  38.     {  
  39.         if(s[iLeft]>0)  
  40.         {  
  41.             return s[iLeft];  
  42.         }else 
  43.         {  
  44.             return 0;  
  45.         }  
  46.     }  
  47.     iCenter = (iLeft+iRight)/2;  
  48.     iMaxLeftSum = SubsequenceSum(s,iLeft,iCenter); //每次递归返回时,该值为该子段的最终左最大子序列和  
  49.     iMaxRightSum = SubsequenceSum(s,iCenter+1,iRight); //每次递归返回时,该值为该子段的右最大自序列和  
  50.     for(int i=iCenter;i>=iLeft;i--) //从中间向左扩展求子段的最大子序列和,必然包括子段的最右端数  
  51.     {  
  52.         iLeftBorderSum+=s[i];  
  53.         if(iLeftBorderSum>iMaxLeftBorderSum)  
  54.         {  
  55.             iMaxLeftBorderSum = iLeftBorderSum; //包含左端数的最大子序列和  
  56.         }  
  57.     }  
  58.     for(int j=iCenter+1;j<=iRight;j++) //从中间向右扩展求子段的最大子序列和,必然包括子段的最左端数  
  59.     {  
  60.         iRightBorderSum += s[j];  
  61.         if(iRightBorderSum > iMaxRightBorderSum)  
  62.         {  
  63.             iMaxRightBorderSum = iRightBorderSum; //包含右端数的最大子序列和  
  64.         }  
  65.     }  
  66.     //返回左子最大序列和,右最大子序列,及横跨中间的最大子序列和三者的最大值  
  67.     return Maxinthree(iMaxLeftSum,iMaxRightSum,iMaxLeftBorderSum+iMaxRightBorderSum);   
  68. }  
  69.  
  70. int Maxinthree(int a,int b,int c)  
  71. {  
  72.     if(b>a)  
  73.         a=b;  
  74.     if(a<c)  
  75.         return c;  
  76.     else 
  77.         return a;  

 









本文转hackfreer51CTO博客,原文链接:http://blog.51cto.com/pnig0s1992/803907,如需转载请自行联系原作者

相关文章
顺序表应用7:最大子段和之分治递归法
顺序表应用7:最大子段和之分治递归法
递归和非递归分别实现求第n个斐波那契数
递归和非递归分别实现求第n个斐波那契数
73 0
利用递归求斐波纳契数列的和
递归的方法更加简单,更容易理解
|
机器学习/深度学习
leetcode-每日一题558. 四叉树交集(分治递归)
时间复杂度:O(n2),其中 n 是四叉树 quadTree1 和 quadTree2 对应矩阵的边长。最坏的情况下,整个矩阵都会被遍历
108 0
leetcode-每日一题558. 四叉树交集(分治递归)
|
机器学习/深度学习 人工智能 算法
『递归』汉诺塔和全排列
使用递归编写一个程序实现汉诺塔问题,要求在输入圆盘数量之后,输出圆盘的移动步骤,输出格式示例如下: 第1步:1号盘从A柱移至B柱第2步:2号盘从A柱移至C柱
226 0
|
机器学习/深度学习 缓存 机器人
从暴力递归到动态规划,记忆化搜索
从暴力递归到动态规划,记忆化搜索
从暴力递归到动态规划,记忆化搜索
|
算法 API
『分治』二分搜索
对于一个规模为n的问题, 1. 若该问题可以容易地解决(比如说规模n较小)则直接解决, 2. 否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同, 3. 递归地解这些子问题, 4. 然后将各子问题的解合并得到原问题的解。 这种算法设计策略叫做分治法。
119 0
循环、递归、分治、回溯、动态规划
循环、递归、分治、回溯、动态规划
128 0