给你一个整数数组 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
提示:
1 <= nums.length <=
- <= nums[i] <=
考虑问题:“找到具有最大和的连续子数组”具有什么特征?
连续子数组一定有一个起始点下标和一个结束点下标。
那么从 i 起始的连续子数组哪个和是最大的?
由于不知道子数组的长度,所以需要从 i 开始遍历,遍历每个可能以 i 开始的子数组,计算和,取最大值。
这也就是暴力遍历的思想。
那么以 i 结束的连续子数组哪个和最大呢?
对于这个问题只需要考虑以 i - 1结束的子数组最大和和当前值的大小,利用动态规划求解。
- 如果为正那么以 i 结束的子数组最大和就等于以 i - 1结束的子数组最大和加nums[ i ]。
- 如果非正,那么说明整个数组的连续子数组最大和不会位于此下标处。
状态转移方程:
dp[i] = max(dp[i - 1] + nums[i],nums[i]);
边界条件,下标为0时,子数组只含有一个元素nums[0]:
dp[0] = nums[0];
完整代码:
class Solution {
public:int maxSubArray(vector<int>& nums) {int n = nums.size();int result = nums[0];vector<int> dp(n,0);dp[0] = nums[0];for(int i = 1;i < n;++i){dp[i] = max(dp[i-1] + nums[i],nums[i]);result = max(result,dp[i]);}return result;}
};
实际上不需要dp数组,可以进行空间优化:
class Solution {
public:int maxSubArray(vector<int>& nums) {int n = nums.size();int result = nums[0];int temp = nums[0];for(int i = 1;i < n;++i){temp = max(temp + nums[i],nums[i]);result = max(result,temp);}return result;}
};