编程题:最大累加和
子数组的最大累加和问题:
给定一个数组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; */ }
当你深入了解,你就会发现世界如此广袤,而你对世界的了解则是如此浅薄,请永远保持谦卑的态度。