Link:leetcode.cn/problems/ma…
Tag:数组、动态规划
难度:Medium
题目
题目描述:给你一个整数数组 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 <= 105-104 <= nums[i] <= 104
题解
思路一:因为数组元素里面有负数,所以滑动数组不太行
思路二:暴力会超时
思路三:看提示可以用动态规划,就有灵感了
起初,设置dp[i][j]=maxvalue,j代表左边界,i代表右边界。改变j进行比较,获得连续子数组和的最大值。【考虑了一下i为左边界、j为左边界的话,没那么方便,好像不能利用动态规划特性(此时的值通过上一个值来更新)】
举例来说,dp[3][0]=max(dp[2][0]+nums[i], ?),感觉?这里需要放的值不太清晰。考虑了之后觉得只需要一个变量即可。dp[i]=nums[i]表示其本身,也是最小子数组,然后不断进行比较。
因为是连续,所以比较当前的值最大还是加上前一个的值最大。
放一个杂乱的草稿截图:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
// 最大和--> 连续
int countSum = accumulate(nums.begin(), nums.end(), 0);
// 暴力枚举--但应该会不行
/* 动态规划 dp[i][j] = maxsum i--子数组右边*/
vector<long>dp(nums.size(), 0);
dp[0] = nums[0];
int maxNum = dp[0];
for(int i = 1; i < nums.size(); i++){
dp[i] = dp[i - 1] + nums[i] > nums[i] ? dp[i - 1] + nums[i]: nums[i];
if(dp[i] > maxNum) maxNum = dp[i];
}
return maxNum;
}
};
复杂度分析: 时间复杂度:O(n) 空间复杂度:O(n) → 优化:由于只依赖于前一个,可以改为滚动数组,则复杂度会降为O(1)