题目描述
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n).
示例1
输入
[1,-2,3,10,-4,7,2,-5]
返回值
18
说明
输入的数组为{1,-2,3,10,—4,7,2,一5},和最大的子数组为{3,10,一4,7,2},因此输出为该子数组的和 18。
此题的意思是,所给数组的所有子集 求出和最大的值。
拿到这道题后我首先想到的是 使用双重for循环,将每个位置的和全部算出来,在求最大值
最后发现很麻烦,而且时间复杂度也不满足。
说来惭愧,学习了一学期算法课,典型的动态规划问题没有看出来。
这里简单说一下动态规划算法:类似与分治算法,将问题进行拆分,再通过递推或者递归解决,只保存最优解,前一问题的解会帮助后一问题的求解。
再来说这个问题:
求所有子集和的最大值
思路:将问题拆解,可以先求出数组前n-1项的最大子序列的和, 用arr[n-1]保存起来,再进行判断,如果它大于0,则arr[n]+arr[n-1] 因为是正数所以加上后肯定会增大,反之前n-1项的和为负数,则不值得继续计算,并置为0,arr[n]不变,从n位置继续计算。最后用max保存最大值即可
代码如下
public int FindGreatestSumOfSubArray(int[] array) {
int max = array[0]; //max 保存最大值
for (int i = 1; i < array.length; i++){
//遍历数组
//array[i-1]保存到当前元素的子序列的最大和
if (array[i-1] < 0){
//如果小于0,则不值得相加置为0,从i位置重新开始
array[i-1] = 0;
}
//加起来
array[i] += array[i-1];
//再用max记录最大值
max = Math.max(max,array[i]);
}
return max;
}
大佬是这样写的,三目运算符还是很简便的
public int FindGreatestSumOfSubArray(int[] array) {
int max = array[0];
for (int i = 1; i < array.length; i++) {
array[i] += array[i - 1] > 0 ? array[i - 1] : 0;
max = Math.max(max, array[i]);
}
return max;
}
时间复杂度O(n)
空间复杂度O(1)