动态规划-最大子数组

看《算法导论》,不过这下可得认真看了,9个月不到就得去找工作了,与我同样的大三党们一样加油咯...

《算法导论》中引入这个问题是通过股票的购买与出售,将前一天的当天的股票差价重新表示出来,即转为了一个最大子数组的问题,具体内容我不多说,转的内容是:

13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7

找到这连续的16个数里面的连续和最大的子数组;

书中练习部分说用设计非递归的,线性时间的算法,我就YY为动态规划处理了;

从数组的左边界开始,从左至右处理,记录到目前为止已经处理过的最大子数组。若已知A[1..j]的最大子数组,基于如下性质将解扩展为A[1...j+1]的最大子数组:A[1...j+1]的最大子数组要么是A[1...j]的最大子数组,要么是某个子数组A[i...j+1](1<=i<=j+1)。在已知A[1...j]的最大子数组的情况下,可以在线性时间内找出形如A[i...j+1]的最大子数组;

思想上述都将出来了,只要将关键点写出即可:

如果前面若干和<0,则其对后面子数组相加无帮助,此时重置dp为array[i],并且记录的起始位置重新标记:

 if(dp[i - 1] <= 0)  //前面的<0,直接丢弃
        {
            dp[i] = array[i];
            temp = i; //记录起始为止
        }


否则,继续往后延伸;

dp[i] = array[i] + dp[i - 1];  //往后求和


最后判断最大子数组值就行,同时标记起始与结束位置:

       if(dp[i] > MaxSumSub)  //找到到i为止的最大子数组
        {
            MaxSumSub = dp[i];  //最大...
            start = temp;  //标记起始
            end = i;  //标记此时的结束位置
        }

java实现的代码如下:

package com.algorithm.chapterfour;

public class DpMaximumSubArray {

	public static void main(String[] args) {
		int[] a=new int[]{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
        System.out.println(MaximumSubArray(a));
	}
    public static int MaximumSubArray(int[] a){
    	int MaxSumSub=Integer.MIN_VALUE; //最大值
    	int start=0,end=0; //最大子数组的开始与结束
    	int[] dp=new int[a.length]; //动态规划的数组
    	dp[0]=a[0];
    	for(int i=1;i<a.length;i++){
    		if(dp[i-1]<=0){
    			dp[i]=a[i];
    			start=i;
    		}else{
    			dp[i]=dp[i-1]+a[i];
    		}
    		if(dp[i]>MaxSumSub){
    			MaxSumSub=dp[i];
    			end=i;
    		}
    	}
    	System.out.println(start+","+end);
    	return MaxSumSub;
    }
}

猜你喜欢

转载自blog.csdn.net/long_lance/article/details/85445768