解法一 贪心算法
局部最优
只有当前的连续和大于0时加上下一个数字才对最大子序和有贡献,一旦当前连续和为负数加上下一个数字就会拉低总和,所以如果当前连续和为负数时就应该重置为0,从下一个元素重新计算。
在局部最优的情况下记录最大的连续和从而达到全局最优
class Solution {
public int maxSubArray(int[] nums) {
int result = Integer.MIN_VALUE;
int count = 0;
for (int i = 0; i < nums.length; i++) {
count += nums[i];
if (count > result) {
result = count;
}
if (count <= 0) {
count = 0;
}
}
return result;
}
}
解法二 动态规化
状态设置:
dp[i]
代表以nums[i]
结尾的最大子序和
状态计算:
显然我们需要求解
m
a
x
0
<
=
i
<
n
(
d
p
(
i
)
)
max_{0<=i<n}(dp(i))
max0<=i<n(dp(i))
class Solution {
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
dp[0] = nums[0];
int result = dp[0];
for (int i = 1; i < nums.length; i++) {
dp[i] = Math.max(dp[i-1] + nums[i], nums[i]);
result = Math.max(dp[i], result);
}
return result;
}
}
空间优化:
可以发现dp[i]只与dp[i-1]有关,因此可以使用一个变量进行优化
class Solution {
public int maxSubArray(int[] nums) {
int pre = nums[0];
int result = pre;
for (int i = 1; i < nums.length; i++) {
pre = Math.max(pre + nums[i], nums[i]);
result = Math.max(pre, result);
}
return result;
}
}