最大子序列和

本博客部分摘选自《算法笔记》(胡凡 曾磊主编,机械工业出版社)
一、动态规划
动态规划(Dynamic programming,简称DP)是把原问题分解为相对简单的子问题的方式求解复杂问题的方法。常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量
二、最大子序列和
如果该问题用暴力破解方法来解决问题,枚举左右端点需要O(n^2)的复杂度,计算两端点之和需要O(n)的复杂度,总的需要O(n^3)复杂度。如果使用前缀和的方法,仍然有O(n^2)的复杂度,当n过大时候是不可承受的。本题的最佳解法是使用动态规划,时间复杂度可以达到O(n)。
假设max[i]表示以a[i]结尾的最大子序列和,而max[i]的求法根据max[i-1]和a[i]来确定:
1)如果序列只有一个元素,那么max[i] = a[i]
2)如果序列有多个元素,那么max[i] = max[i-1]+a[i]
所以max[i] = max{a[i],max[i-1]+a[i]},这个公式就是动态规划的地推公式,也是动态规划的难点。
最终整个序列的最大子序列和就是求max数组中的最大元素,例如序列-2、11、-4、13、-5、-2
max[0] = -2
max[1] = 11
max[2] = 7
max[3] = 20
max[4] = 15
max[5] = 13
所以该序列的最大子序列和是max[3] = 20
三、代码

public static int MaxSubSum(int[] a){
        //dp[i]表示以arr[i]结尾的最大子序列和
        int[] max = new int[a.length];
        //第一个元素max[0]和a[0]相等
        max[0] = a[0];
        //记录最终结果,假设第一个最大
        int result = max[0];
        //从头开始递推
        for(int i=1;i<a.length;i++){
            max[i] = max(max[i-1]+a[i], a[i]);
            //寻找max数组最大值
            if(max[i]>result){
                result = max[i];
            }
        }
        return result;
    }
    /* 取两个数的最大值*/
    public static int max(int i,int j){
        if(i<j){
            return j;
        }
        return i;
    }

猜你喜欢

转载自blog.csdn.net/ae86jaychou/article/details/79422856
今日推荐