最大子序列和的【分治递归】求法

首先标明递归的四要素:

关于(1)基准情形,是说必须有不用递归就能求解的情况。否则,递归将永远进行下去。
可以看下这个例子:
int badRecursion( int n )
{
        if ( n == 0 )
            return 0;
        else 
            return badRecursion ( n/3 + 1 ) + n - 1;
}
你可以算一下,当计算到badRecursion(1)时,将一直计算下去。因为他没有一个终止循环的条件。

(2)(3)很好理解,就不说了。
(4)是说递归算法的效率性。
可以看一下这个递归算法:
long fib(int n)
{
    if ( n <= 1 )
        return 1;
    else
        return fib( n - 1 ) + fib( n - 2 );
}
这个算法看起来是个递归,可是当把n的数值调大后会发现它的效率低的惊人。简单分析一下就可以看出,最后一行语句第一次调用 fib(n-1) 实际上同时计算了fib(n-2)。这个信息被抛弃而在最后一行语句第二次调用时又重新计算了一遍。这违反了准则(4)。这可以解释为什么不用递归计算斐波那契数了。

下面是代码和注解

 1 int  maxSumRec(const vector<int>&a,int left,int right)
 2
 3 {
 4
 5     int maxLeftSum,maxRightSum; //表示
 6
 7     int rightBorderSum = 0,leftBorderSum = 0;
 8
 9     int maxLeftBorderSum = 0,maxRightBorderSum = 0;
10
11     int center;
12
13     if(left == right) //解决小容量情况,当序列只有一个元素时,非负则返回唯一值,否则返回0(基准情况)
14
15     {
16
17         if(a[left]>0)
18
19         {
20
21             return a[left];
22
23         }else
24
25         {
26
27             return 0;
28
29         }
30
31     }
32
33     center = (left+right)/2;
34
35     maxLeftSum = maxSumRec(s,left,center); //每次递归返回时,该值为该子段的最终左最大子序列和
36
37     maxRightSum = maxSumRec(s,center+1,right); //每次递归返回时,该值为该子段的右最大自序列和
38
39     for(int i=center;i>=left;i--) //从中间向左扩展求子段的最大子序列和,必然包括子段的最右端数
40
41     {
42
43         leftBorderSum+=s[i];
44
45         if(leftBorderSum>maxLeftBorderSum)
46
47         {
48
49             maxLeftBorderSum = leftBorderSum; //包含左端数的最大子序列和
50
51         }
52
53     }
54
55     for(int j=center+1;j<=right;j++) //从中间向右扩展求子段的最大子序列和,必然包括子段的最左端数
56
57     {
58
59         rightBorderSum += a[j];
60
61         if(rightBorderSum > maxRightBorderSum)
62
63         {
64
65             maxRightBorderSum = rightBorderSum; //包含右端数的最大子序列和
66
67         }
68
69     }
70
71     //返回左子最大序列和,右最大子序列,及横跨中间的最大子序列和三者的最大值
72
73     return max3(maxLeftSum,maxRightSum,maxLeftBorderSum+maxRightBorderSum);
74
75 }   
时间: 2025-01-09 12:48:17

最大子序列和的【分治递归】求法的相关文章

分治递归:求数组元素的最大值,最小值

//分治递归,求数组元素的最大值,最小值 /** * 保存产生的最大值,最小值 * @author Administrator * */ public class Values { private int max; private int min; public Values(int max,int min){ this.max=max; this.min=min; } public int getMax() { return max; } public void setMax(int max)

斐波那契数列高效递归求法

时间:2014.05.19 地点:图书馆 ------------------------------------------------------------------- 一.简述 前面给出了一种斐波那契数列解法的矩阵幂方法,这是最高效的方法,时间复杂度为O(log).正常来说通过递推公式 F(n)=F(n-1)+F(n-2)直接来计算F(n)效率是很差的,因为这里会涉及很多冗余计算,比如求F(5),我们要求[F(4)和F(3)],[要求F(4)则得求F(3)和F(2),要求F(3)得求F

归并排序 分治+递归

0      1    2     3     4     5     6     7     8   //下标 {  9  ,  4  ,  3  ,  7  ,  3  ,  8  ,  2  ,  4  ,  8  }//通过mergesort函数递归 来切 开始的时候fir=0, las=8, mid=4  所以下标0-4,分为前组   5-8分为后组 {  9  , 4   ,  3  ,  7  ,  3 }{ 8   , 2   , 4  ,  8  } {  9   , 4  ,

求最大子数组的和,算法导论只分治递归求解,暴力求解,记忆扫描方法。

#include<iostream> #include<vector> using namespace std; /*******************************************************************************************/ // 分治方法,利用递归的思想 // ugly_chen 2014.11.3 22:24 //说明:把数组分为两部分,右边部分和左边部分,要不就是右边部分和左边部分之和. // ---

BZOJ 1621 [Usaco2008 Open]Roads Around The Farm分岔路口:分治 递归

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1621 题意: 约翰的N(1≤N≤1,000,000,000)只奶牛要出发去探索牧场四周的土地. 她们将沿着一条路走,一直走到三岔路口(可以认为所有的路口都是这样的). 这时候,这一群奶牛可能会分成两群,分别沿着接下来的两条路继续走. 如果她们再次走到三岔路口,那么仍有可能继续分裂成两群继续走. 奶牛的分裂方式十分古怪:如果这一群奶牛可以精确地分成两部分,这两部分的牛数恰好相差K(1≤K≤

【LEETCODE】68、分治递归,medium级别,题目:95、120、91

package y2019.Algorithm.dynamicprogramming.medium; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.dynamicprogramming.medium * @ClassName: NumDecodings * @Author: xiaof * @Description: 91. Decode Ways * A message containing letters from

fibo数求法(递归版本) -- 作者小泽

fibonacci数的递归求法: 1 2 struct Fib 3 { 4 int x1; 5 int x2; 6 }; 7 8 Fib fib(int x) 9 { 10 Fib ans; 11 if(x == 2) 12 { 13 ans.x1 = 0; 14 ans.x2 = 1%MOD; 15 return ans; 16 } 17 Fib temp; 18 int x1 = x/2, x2 = x1 - 1; 19 if(x1%2) 20 { 21 temp = fib(x2); 22

基础算法记录——由最大子序列和想到的

这是一个入门级的算法,但它却揭示了计算机算法设计的一些核心思想:枚举与分治递归. 这篇文章主要由简单到复杂来解析这一问题,流程大致是:枚举求解(充分利用计算机的计算能力来解决单调复杂问题),算法分析与改进(相对偏移化简枚举法),分治算法(divide-conquer,计算机核心思想之一),递归算法与递归的使用原则,最后依然使用算法分析的技术来改进上面的算法. 1)枚举法,这应该是计算机从业人员最熟悉,最简单的算法.想想你以前写过的那些程序,现在回头再看时,估计自己都会被恶心到.但是当你再过几年c

分治法求最大子序列

给定一个序列,下标为 i, i+1, i+2, ...... , j,设 mid = (i+j)/2, 则最大子序列可能出现的地方有三个,mid的左边,mid的右边,或者在中间(包括mid).只要求出左边和右边的最大子序列(子问题),和边界上左边和右边最大子序列的和,找出三个子序列中最大的即可. #include <iostream> using namespace std; /*分治法解决最大子序列问题*/ int MaxSubSum(const int a[], int left, int