【每日刷题】Day119
🥕个人主页:开敲🍉
🔥所属专栏:每日刷题🍍
🌼文章目录🌼
1. 918. 环形子数组的最大和 - 力扣(LeetCode)
2. 152. 乘积最大子数组 - 力扣(LeetCode)
3. 1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode)
1. 918. 环形子数组的最大和 - 力扣(LeetCode)
//思路:子数组动态规划问题。
//本题核心思路与 Day 118 中 "最大子数组和" 思路一样。具体过程看图解:
class Solution {
public:
const int INF = 0x3f3f3f3f;
int maxSubarraySumCircular(vector<int>& nums)
{
int n = nums.size(),tmp1 = -INF,tmp2 = INF,sum = nums[0];
vector<int> dp(n);
dp[0] = nums[0];
auto dp1 = dp;
for(int i = 1;i<n;i++)
{
dp[i] = max(nums[i],nums[i]+dp[i-1]);//中间的最大子数组和
dp1[i] = min(nums[i],nums[i]+dp1[i-1]);//中间的最小子数组和
sum+=nums[i];//整个数组的和
}
for(int i = 0;i<n;i++)
{
tmp1 = tmp1>dp[i]?tmp1:dp[i];
tmp2 = tmp2<dp1[i]?tmp2:dp1[i];
}
if(tmp2==sum) return tmp1;//[-3,-2,-3]特殊情况,最小子数组和就是整个数组
return max(tmp1,sum-tmp2);
}
};
2. 152. 乘积最大子数组 - 力扣(LeetCode)
//思路:子数组动态规划问题。
//本题思路与我们的 Day 118 中的 "最大子数组和" 问题十分相似,但是状态数组和方程差别很大:
class Solution {
public:
const int INF = 0x3f3f3f3f;
int maxProduct(vector<int>& nums)
{
int n = nums.size(),ans = -INF;
vector<int> f(n);
f[0] = nums[0];
auto g = f;
for(int i = 1;i<n;i++)
{
f[i] = max(nums[i],nums[i]*f[i-1]);
g[i] = min(nums[i],nums[i]*g[i-1]);
if(nums[i]<0)
{
f[i] = max(nums[i],nums[i]*g[i-1]);
g[i] = min(nums[i],nums[i]*f[i-1]);
}
}
//最后的结果只可能出现在 f[i] 中
for(int i = 0;i<n;i++) ans = ans>f[i]?ans:f[i];
return ans;
}
};
3. 1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode)
//思路:子数组动态规划问题。
class Solution {
public:
const int INF = 0x3f3f3f3f;
int getMaxLen(vector<int>& nums)
{
int n = nums.size(),ans = -INF;
vector<int> f(n+1),g(n+1);
for(int i = 1;i<=n;i++)
{
if(nums[i-1]>0)
{
f[i] = f[i-1]+1;
g[i] = g[i-1]==0?0:g[i-1]+1;
}
else if(nums[i-1]<0)
{
f[i] = g[i-1]==0?0:g[i-1]+1;
g[i] = f[i-1]+1;
}
//写入的同时更新结果,结果只可能出现在 f[i] 中
ans = max(ans,f[i]);
}
return ans;
}
};