递归调用分析-最大自序列求和问题

昨天开始看《数据结构与算法分析-java语言描述》这本书,在第二章举例了一个算法问题“最大子序列和问题”,在第三种递归方法,由于开始并没有很好理解,递归调用在算法中有很重要,用了最简单一个例子来加深理解!(当然这种方法在这四种算法中不是最优的)。


先给出源代码:

package secondCHA;
 
public class maxSUM3 {
   
	static int MaxSubSum( int A[], int Left, int Right)  //问题?初始left和right是先给定的吗?值是多少
	{  
	    int MaxLeftSum,MaxRightSum;  
	    int MaxLeftBorderSum,MaxRightBorderSum;  
	    int LeftBorderSum,RightBorderSum;  
	    int Center,i;  

		//递归终点,left>right的情况是不可能出现的,除非N是负数。
	    if(Left == Right)                              
	    {  
	        if(A[Left] > 0)  
	            return A[Left];  
	        else  
	            return 0;  
	    }  
	      
	    Center = (Left + Right)/2;  
	    //重点,递归部分
		MaxLeftSum = MaxSubSum(A,Left,Center);  
	    MaxRightSum = MaxSubSum(A,Center+1,Right);  
	     

		// 计算left达到中间分界处的两个最大和的和数
	    MaxLeftBorderSum = 0;  
	    LeftBorderSum = 0;  
	    for(i = Center;i >= Left;i--)  
	    {  
	        LeftBorderSum += A[i];  
	        if(LeftBorderSum > MaxLeftBorderSum)  
	            MaxLeftBorderSum = LeftBorderSum;  
	    }  
	    
		// 计算right达到中间分界处的两个最大和的和数
	    MaxRightBorderSum = 0;  
	    RightBorderSum = 0;  
	    for(i = Center+1;i <= Right;i++)  
	    {  
	        RightBorderSum += A[i];  
	        if(RightBorderSum > MaxRightBorderSum)  
	            MaxRightBorderSum = RightBorderSum;  
	    }     
	      
	    return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum);  
	}   
	  
	static int Max(int a, int b, int c)  
	{  
	    if(a>b&&a>c)  
	        return a;  
	    else if(b>a&&b>c)  
	        return b;  
	    else  
	        return c;   
	}  
	public static void main(String[] args) { 
		// TODO Auto-generated method stub
		 int[] a={4,-3,5,-2,-1,2,6,-2};
		 int left=0;
		 int right=a.length-1;
		 System.out.println(MaxSubSum(a,left,right));
	}
 
}

用8个元素的数组进行分析:

A0

A1

A2

A3

A4

A5

A6

A7

4

-3

5

-2

-1

2

6

-2

第一次:MaxSubSum(A,0,7)

A0

A1

A2

A3

A4

A5

A6

A7

4

-3

5

-2

-1

2

6

-2

Int center=(0+7)/2=3

左边(A0-A3)部分包含最后一个元素的最大值为:

LeftBorderSum=Max(A3,A3+A2,A3+A2+A1,A3+A2+A1+A0)=4

右边(A4-A7)部分包含第一个元素的最大值为:

RightBorderSum=Max(A4,A4+A5,A4+A5+A6,A4+A5+A6+A7)=7

return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum=11);

MaxSubSum(A,0,7)=return Max(MaxSubSum(A,0,3),MaxSubSum(A,4,7),11);

第一次的返回值采用了中MaxLeftSum = MaxSubSum(A,0,3)和MaxRightSum = MaxSubSum(A,4,7)采用了递归,则需先确定MaxSubSum(A,0,3)和MaxSubSum(A,4,7),因为引出了第二次分析。

 

第二次MaxSubSum(A,0,3),MaxSubSum(A,4,7)

1  MaxSubSum(A,0,3)

A0

A1

A2

A3

4

-3

5

-2

Int center=(0+3)/2=1

左边(A0-A1)部分包含最后一个元素的最大值为:

LeftBorderSum=Max(A1,A1+A0,)=1

右边(A2-A3)部分包含第一个元素的最大值为:

RightBorderSum=Max(A2,,A2+A3)=5

return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum=6);

MaxSubSum(A,0,3)=return Max(MaxSubSum(A,0,1),MaxSubSum(A,2,3),6);

2 MaxSubSum(A,4,7)

A4

A5

A6

A7

-1

2

6

-2

Int center=(4+7)/2=5

左边(A4-A5)部分包含最后一个元素的最大值为:

LeftBorderSum=Max(A5,A5+A4)=2

右边(A6-A7)部分包含第一个元素的最大值为:

RightBorderSum=Max(A6,A6+A7)=6

return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum=8);

MaxSubSum(A,4,7)=return Max(MaxSubSum(A,4,5),MaxSubSum(A,6,7),8);

 

第三次MaxSubSum(A,0,1),MaxSubSum(A,2,3),MaxSubSum(A,4,5),MaxSubSum(A,6,7)

1.1 MaxSubSum(A,0,1)

A0

A1

4

-3

MaxSubSum(A,0,1)=return Max(MaxSubSum(A,0,0),MaxSubSum(A,1,1),1);

1.2 MaxSubSum(A,2,3)

A2

A3

5

-2

MaxSubSum(A,2,3)=return Max(MaxSubSum(A,2,2),MaxSubSum(A,3,3),3);

2.1 MaxSubSum(A,4,5)

A4

A5

-1

2

MaxSubSum(A,4,5)=return Max(MaxSubSum(A,4,4),MaxSubSum(A,5,5),1);

2.2 MaxSubSum(A,6,7)

A6

A7

6

-2

MaxSubSum(A,6,7)=return Max(MaxSubSum(A,6,6),MaxSubSum(A,7,7),4);

 

第四次MaxSubSum(A,0,0),MaxSubSum(A,1,1),MaxSubSum(A,2,2),MaxSubSum(A,3,3),MaxSubSum(A,4,4),MaxSubSum(A,5,5),MaxSubSum(A,6,6),MaxSubSum(A,7,7)

这时到达递归终点,由left=right

    if(Left == Right)                              

    {  

        if(A[Left] > 0)  

            return A[Left];  

        else  

            return 0;  

    }  

因此:MaxSubSum(A,0,0)=4,MaxSubSum(A,1,1)=0,MaxSubSum(A,2,2)=5,MaxSubSum(A,3,3)=0,MaxSubSum(A,4,4)=0,MaxSubSum(A,5,5)=2,MaxSubSum(A,6,6)=6,MaxSubSum(A,7,7)=0

递归结束,则将递归终点按第四次-第三次-第二次-第一次返回。

MaxSubSum(A,0,0)=4,MaxSubSum(A,1,1)=0,MaxSubSum(A,2,2)=5,MaxSubSum(A,3,3)=0,MaxSubSum(A,4,4)=0,MaxSubSum(A,5,5)=2,MaxSubSum(A,6,6)=6,MaxSubSum(A,7,7)=0.

 

MaxSubSum(A,0,1)=return Max(MaxSubSum(A,0,0),MaxSubSum(A,1,1),1)=4

MaxSubSum(A,2,3)=return Max(MaxSubSum(A,2,2),MaxSubSum(A,3,3),3)=5

MaxSubSum(A,4,5)=return Max(MaxSubSum(A,4,4),MaxSubSum(A,5,5),1)=2;

MaxSubSum(A,6,7)=return Max(MaxSubSum(A,6,6),MaxSubSum(A,7,7),4)=6

 

MaxSubSum(A,0,3)=return Max(MaxSubSum(A,0,1),MaxSubSum(A,2,3),6)=6

MaxSubSum(A,4,7)=return Max(MaxSubSum(A,4,5),MaxSubSum(A,6,7),8)=8

 

MaxSubSum(A,0,7)=return Max(MaxSubSum(A,0,3),MaxSubSum(A,4,7),11)=11

 

总结:在理解递归的时候可以把他看做一个黑盒子,采用归纳证明发的思想,重点关注递归终点和递归方法。例如本例子中,这个方法的思想是,最大子序列可能有三种情况:左边,右边和包含左右挨着的元素组。就可以求左边最大,右边最大,左右同时包含最大,这三者中的最大值,其中左右同时包含的最大值是可以求得的,因此只需求左最大和右最大,这里又可以把左最大和右最大看成2个独立元素组......递归循环。递归终点,就是进入死循环或者无法继续,这时当left=right时,就需要终点程序。

你可能感兴趣的:(java)