问题描述
问题分析
使用动态规划来解题是比较常见的思路,不多赘述了。这里考虑使用贪心的思想;
首先要搞清楚一个概念:增益。假设现在有一个连续子序列N,和接下来的一个数字a。我们知道,要得到最大的子序列和,我们首先要判断a的值是否大于0,若a大于0,这说明a对于N的和有正向增益,两者结合起来的和肯定比原来的N要大,那么这个a就可以添加到子序列N中来,这样我们就找到了一个更大的子序列和,然后继续迭代。
那么我们可以反过来思考:已知上文提到的N与a,若N的和大于0,那么对于a来说,两者结合起来是有正向增益的,可以结合起来变成一个更大的子序列和;若N的和小于0或者等于0,那么对于a来说,N序列里面那么多数字全都是废的,没有任何作用,干脆不要了,继续找后面的数字吧!
反过来的好处就是可以一次遍历序列解决问题!若正向思路,你遇到一个负数之后就不知道该如何处理了。
解法:贪心
- 时间复杂度:O( n ),其中n表示数组的长度。
Java代码
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
// int[] a = {-2,1,-3,4,-1,2,1,-5,4};
int[] a = {1};
System.out.println(maxSubArray(a));
}
static public int maxSubArray(int[] nums) {
int maxSum = nums[0];
int now = 0; // 增益
for (int i: nums) {
if (now > 0){
//若上轮增益>0,则可以添加这个数字,至于添加之后的结果怎样,待下一轮判断
now += i;
}else {
//若上一轮计算增益已经是负效益,那么直接从当前数字重新开始计算
now = i;
}
//每轮添加完这个数字,都要更新最大值
maxSum = Math.max(maxSum, now);
}
return maxSum;
}
}
结果分析
以上代码的执行结果:
执行时间 | 内存消耗 |
---|---|
1 ms | 38.1 MB |