连续子数组的最大和

题目描述

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组,求所有子数组的和的最大值。
要求时间复杂度为$O(n)$。

示例1:

1
2
3
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

提示:

  • 1 <= arr.length <= 10^5
  • -100 <= arr[i] <= 100

题目链接

Leetcode

题目解答

1
2
3
4
假设nums数组长度为n,下标从0~n-1
用f(i)表示以下标i结尾的子数组最大和
f(i)的状态转移方程如下:
f(i) = max{f(i-1) + nums[i], nums[i]}

动态规划,根据状态转移方程,我们用一个新数组依次记录每一个下标元素作为结尾的子数组和的最大值,然后将这个值与全局的最大值比较,全局最大值的最终结果就是所有子数组和的最大值。

时间复杂度:$O(n)$ 空间复杂度:$O(n)$

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
int maxSum = nums[0];
dp[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
maxSum = Math.max(dp[i], maxSum);
}
return maxSum;
}
}

执行用时:1 ms, 在所有 Java 提交中击败了94.77%的用户
内存消耗:38.4 MB, 在所有 Java 提交中击败了66.93%的用户

借助滚动数组思想,定义一个变量curSum用来记录f(i-1)的值,这样可以不使用额外的数组,空间复杂度降到了$O(1)$。

时间复杂度:$O(n)$ 空间复杂度:$O(1)$

1
2
3
4
5
6
7
8
9
10
class Solution {
public int maxSubArray(int[] nums) {
int curSum = 0, maxSum = nums[0];
for (int num : nums) {
curSum = Math.max(curSum + num, num);
maxSum = Math.max(curSum, maxSum);
}
return maxSum;
}
}

执行用时:1 ms, 在所有 Java 提交中击败了94.77%的用户
内存消耗:38.2 MB, 在所有 Java 提交中击败了86.58%的用户

-------------本文结束 感谢您的阅读-------------

文章对您有帮助,可以打赏一杯咖啡,鼓励我继续创作!