这道题典型的用动态规划去解决。
方法一
方法一是用一个一维的数组 dp[i] 去存储结果,dp[i] 的含义是“以第i个元素结尾的子数组的元素之和最大值”,其中i的值为0~n-1,n是nums数组的大小。初始化 dp[0]=nums[0],dp数组的递推公式为 dp[i] = max( dp[i-1] + nums[i], nums[i] ),在遍历的时候从下标1开始,从数组的递推公式看出:连续的整数组成子数组中较大值是dp[i-1]+nums[i]或者nums[i]。
如果是其他类型的动态规划,取的值可能就是dp[i-1]+nums[i]或者dp[i-1],很容易出错。遍历完成之后,找出dp数组中的最大值。代码如下:
class Solution
{
public:
int maxSubArray(vector<int>& nums) {
if(nums.size()==1)return nums[0];
vector<int>dp(nums.size());
dp[0]=nums[0];
for(int i=1; i<nums.size(); i++)
{
dp[i]=max(nums[i],dp[i-1]+nums[i]);
}
return *max_element(dp.begin(),dp.end());
}
};
方法二
方法二把方法一的dp数组压缩成一个数,空间复杂度是O(1),
从dp[i] = max ( nums[i], dp[i-1]+nums[i] )看出dp数组的每个元素只访问了一次,存在空间浪费,换句话说是当前dp数组的状态只和它前一个dp数组的状态有关系,和其他的dp数组元素无关,所以可以压缩。由于压缩会导致无法记录遍历过程中的最大子数组之和,所以还需要一个maxAns记录每一次遍历的最大值。代码如下:
class Solution
{
public:
int maxSubArray(vector<int>& nums) {
int pre=nums[0],maxAns=nums[0];
for(int i=1;i<nums.size();i++){
pre=max(nums[i],pre+nums[i]);
maxAns=max(maxAns,pre);
}
return maxAns;
}
};