动态规划,前缀和,维护状态更新。
从题可以看出,找的是最大和的连续子数组,即一个数组中的其中一个连续部分。从前往后遍历,每遍历到一个数可以尝试做叠加,注意是尝试,因为有可能会遇到一个很大的负数,把前面加起来的都抵消掉,显然不是所要的,因此在dp中需要一个做结果集的维护,与更新后的总数做比较,看看是否需要做更新。
class Solution {
public int maxSubArray(int[] nums) {
int[] f = new int[nums.length];
f[0] = nums[0];
int ans = f[0];
for (int i = 1; i < nums.length; i++) {
f[i] = Math.max(f[i - 1], 0) + nums[i];
ans = Math.max(ans, f[i]);
}
return ans;
}
}
然后这里用类似滚动数组的思想做优化,可以少用一个数组做空间复杂度上的优化。
class Solution {
public int maxSubArray(int[] nums) {
int ans = Integer.MIN_VALUE;
int f = 0;
for (int x : nums) {
f = Math.max(f+ x, x) ;
ans = Math.max(ans, f);
}
return ans;
}
}
这题还可以用前缀和实现,子数组的元素和等于两个前缀和的差,可以一边遍历数组计算前缀和,一边维护前缀和的最小值。由于题目要求子数组不能为空,应当先计算前缀和减去最小前缀和,再更新最小前缀和。
时间复杂度:O(n),空间复杂度:O(1)。
class Solution {
public int maxSubArray(int[] nums) {
int ans = Integer.MIN_VALUE;
int minPreSum = 0;
int preSum = 0;
for (int x : nums) {
preSum += x;
ans = Math.max(ans, preSum - minPreSum);
minPreSum = Math.min(minPreSum, preSum);
}
return ans;
}
}
动态规划要找准状态转移方程及所需更新的状态。