「这是我参与2022首次更文挑战的第34天,活动详情查看:2022首次更文挑战」。
最大子数组和
题目描述
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1 :
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2 :
输入:nums = [1]
输出:1
示例 3 :
输入:nums = [5,4,-1,7,8]
输出:23
解法一 : 暴力解
一般情况下,先从暴力解分析,然后再进行一步步的优化。
原始暴力解: (超时,仅供参考)
求子序列和,那么我们要知道子序列的首尾位置,然后计算首尾之间的序列和。用 2 个 for 循环可以枚举所有子序列的首尾位置。 然后用一个 for 循环求解序列和。这里时间复杂度太高,O(n^3)
.
代码:
class Solution {
public int maxSubArray(int[] nums) {
int len = nums.length;
int maxSum = Integer.MIN_VALUE;
int sum = 0;
for (int i = 0; i < len; i++) {
sum = 0;
for (int j = i; j < len; j++) {
sum += nums[j];
maxSum = Math.max(maxSum, sum);
}
}
return maxSum;
}
}
解法二 : 动态规划
动态规划的难点在于找到状态转移方程,
dp[i] - 表示到当前位置 i 的最大子序列和
状态转移方程为: dp[i] = max(dp[i - 1] + nums[i], nums[i])
初始化:dp[0] = nums[0]
从状态转移方程中,我们只关注前一个状态的值,所以不需要开一个数组记录位置所有子序列和,只需要两个变量,
currMaxSum - 累计最大和到当前位置i
maxSum - 全局最大子序列和
:
currMaxSum = max(currMaxSum + nums[i], nums[i])
maxSum = max(currMaxSum, maxSum)
代码:
class Solution {
public int maxSubArray(int[] nums) {
int currMaxSum = nums[0];
int maxSum = nums[0];
for (int i = 1; i < nums.length; i++) {
currMaxSum = Math.max(currMaxSum + nums[i], nums[i]);
maxSum = Math.max(maxSum, currMaxSum);
}
return maxSum;
}
}