编程题:最大累加和

子数组的最大累加和问题

给定一个数组arr,返回子数组的最大累加和
例如,arr = [1, -2, 3, 5, -2, 6, -1],所有子数组中,[3, 5, -2, 6]可以累加出最大的和12,所以返回12.
题目保证没有全为负数的数据
[要求]
时间复杂度为O(n)O(n),空间复杂度为O(1)O(1)

考察点:动态规划

思路:

动态规划基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。若我们定义了每个子问题的解是S[i],我们需要做的是找出并定义S[i]的含义,与其规律。

最简单的是直接将S[i]定义为i及i之前序列中的最大累加和,但是这样子定义,我们找不出规律来,S[0],S[1]……到S[i]之前并无联系。

但是以S[i]=从i位置往前累加的最大累加和,那么i位置的S[i]的计算方式则是要么是ai本身,要么是ai+S[i-1],因为S[i-1]是从i-1位置往前累加的最大累加和。以这个规律构建的动态规划矩阵,区矩阵中的最大值则是所求的最大累加和。

解题:

对于数组{a0,a1,a2,a3……an}求最大累加和maxSum,可分解为求数组从0到i并且包含ai的最大累加和s[i](0<=i<=n)。

s[0]:从a[0]位置往前累加的最大值是max(0,a0)--这里是个例外,我们可以不把a[0]放入累加和里,不会断掉后面的累加

s[1]:  数组从0到1,并且包含a1的最大累加和是max(a1,a1+s[0])。这里取的是a0+a1,a1中的最大值

s[2]:  数组从0到2,并且包含a2的最大累加和是max(a2,a2+s[1])。由于s[1]是a0+a1,a1中的最大值,那么s[2]取的则是a0+a1+a2,a1+a2,a2中的最大值

……

s[i]:数组从0到i,并且包含ai的最大累加和是max(ai,ai+s[i-1])。

/*
 从节点i往前最大的累加和s[i]=a[i]和a[i]+s[i-1]中较大的一个,限制时间和空间。
1、使用递归(使用递归的时间效率较差)
2、使用循环数组从节点0开始存储,由于限制空间,直接在传入的数组中操作,返回s[i]中最大的一个。
3、使用循环。只保存s[i-1]的值用于计算和保存max的值
*/
    /**
     * max sum of the subarray 最大累加和
     * @param arr int整型一维数组 the array
     * @return int整型
     */
    public int maxsumofSubarray (int[] arr) {
        
       if(arr.length==0) return 0;
        /*方法一:数组保存最大累加和*/
       int max=Math.max(0,arr[0]);
       for(int i=1;i<arr.length;i++){
           arr[i] = Math.max(arr[i],arr[i-1]+arr[i]);
           max = Math.max(max,arr[i]);
       }
        return max;
        /*方法二:不保存数组,只保存preSum和maxSum*/
        /*
        int preSum = Math.max(0,arr[0]);
        int maxSum = preSum;
        for(int i=1;i<arr.length;i++){
           preSum = Math.max(arr[i],preSum+arr[i]);
           maxSum = Math.max(maxSum,preSum);
       }
        return maxSum;
        
        */
        
       
    }

 

posted @ 2021-04-23 17:26  l.w.x  阅读(122)  评论(0编辑  收藏  举报