目录
1.状态表示
dp[i]:表示以i位置为结尾最大子数组的和
2.状态转移方程
当dp[i-1] <= 0, nums[i] >= 0 时,dp[i] = dp[i-1] + nums[i]
当dp[i-1] >= 0, nums[i] >=0时,dp[i] = dp[i-1] + nums[i]
当dp[i-1] >= 0, nums[i] <= 0 时, dp[i] = dp[i-1] + nums[i]
当dp[i-1] <=0, nums[i] <= 0时, dp[i] = num[i]
综合上面四种情况 dp[i] = max(nums[i], dp[i] = dp[i-1] + nums[i]);
3.初始化
因为状态转移方程用到了i-1,所以需要初始化0位置
dp[0] = nums[0];
4.返回值
将dp数组中出现的最大值返回。
class Solution {
public:
//dp[i] 表示以i位置为结尾子数组的最大和
//dp[i] = max(nums[i],dp[i-1]+nums[i]);
int maxSubArray(vector<int>& nums)
{
int n = nums.size();
vector<int> dp(n);
dp[0] = nums[0];
int ret = 0;
ret = nums[0];
for(int i = 1; i < n; i++)
{
dp[i] = max(nums[i],dp[i-1]+nums[i]);
ret = max(ret,dp[i]);
}
return ret;
}
};
918. 环形子数组的最大和
1.状态表示
dp[i]:表示以i位置为结尾最大子数组的和
2.状态转移方程
最大子数组无非就是两种情况
第一种就像第一道题一样,最大子数组时正常连续的。
第二种就是数组的头部和尾部各占一部分。
第一种情况的的化就是第一道题的做法。
第二种情况可以使用取反的方法,数组的总和是固定的,只需求出中间连续最小子数组,用数组的总和 - 连续最小的子数组 = 第二种情况的最大子数组和
f[i]表示最大连续子数组之和,g[i]表示最小连续子数组之和。
f[i] = max(num[i], f[i-1] + nums[i]);
g[i] = min(num[i], f[i-1] + nums[i]);
3.初始化
f[0] = g[0] = nums[0];
4.返回值
需要记录 f[i]出现的最大值fmax,和g[i]出现的最小值gmin
返回 max(fmax, sum - gmin);
但是有一个特殊情况数组的元素都为负数的时候 sum = gmin,这样会返回0,特殊处理一下。
sum == gmin ? fmax : max(fmax, sum - gmin);
class Solution {
public:
int maxSubarraySumCircular(vector<int>& nums)
{
int n = nums.size();
vector<int> f(n);
auto g = f;
if(n == 1)
{
return nums[0];
}
f[0] = nums[0];
g[0] = nums[0];
int sum = nums[0];
int fmax = INT_MIN, gmin = 400000;
for(int i = 1; i < n; i++)
{
sum += nums[i];
f[i] = max(nums[i], f[i-1] + nums[i]);
g[i] = min(nums[i], g[i-1] + nums[i]);
fmax = max(fmax, f[i]);
gmin = min(gmin, g[i]);
}
return sum == gmin ? fmax : max(fmax, sum - gmin);
}
};
152. 乘积最大子数组
1.状态表示
dp[i]:表示i位置结尾乘积最大和的子数字
2.状态转移方程
f[i]:表示i位置结尾乘积最大和的子数组
g[i]:表示i位置结尾乘积最小和的子数组
f[i-1] >=0, nums[i] >= 0, f[i] = f[i-1] * nums[i]
f[i-1] <= 0,nums[i] <=0, f[i] = g[i-1] * nums[i]
f[i-1] >=0, nums[i] <= 0, f[i] = nums[i]
f[i-1] <=0, nums[i] >= 0,f[i] = nums[i]
综上所诉f[i] = max(nums[i], f[i-1] * nums[i], g[i-1] * nums[i]);
g[i] = min(nums[i], f[i-1] * nums[i], g[i-1] * nums[i]);
3.初始化
f[0] = g[0] = nums[0];
4.返回值
返回f[i]出现的最大值
class Solution {
public:
int maxProduct(vector<int>& nums)
{
int n = nums.size();
vector<int> f(n), g(n);
f[0] = g[0] = nums[0];
int ret = f[0];
for(int i = 1; i < n; i++)
{
f[i] = max(nums[i], max(f[i-1] * nums[i], g[i-1] * nums[i]));
g[i] = min(nums[i], min(f[i-1] * nums[i], g[i-1] * nums[i]));
ret = max(ret, f[i]);
}
return ret;
}
};