前言
在本文章中,我们将要详细介绍一下Leetcode(面试题 08.01.)三步问题相关的内容
918. 环形子数组的最大和
题目讲解
算法原理
1.状态表示
我们想想结果可能出现的情况!!!
1.环形子数组的最大和区间就在中间位置
2.环形子数组的最大和区间左边一段,右边一段。
这就可以每个位置都可以是起始位置。
我们计算起来比较麻烦。我们可以用正难则反
我们知道整个数组的总和是多少,那么我们求出子数组的最小值。
用总和减去这个最小值就是我们所要的结果。
f[i]:到达i位置,此时环形子数组的最大和
g[i]:到达i位置,此时环形子数组的最小和
2.状态转移方程
f[i ]=max(f[i-1]+nums[i],nums[i]);
g[i]=max(g[i-1]+nums[i],nums[i]);
3.初始化
f[0]=g[0]=nums[0];
4.填表顺序
从左到右,两个表一起填写
5.返回值是什么
我们返回的是环形子数组的最大和。
最大和可能出现在上面两种情况中,我们需要再进行比大小。
每一个位置都可以是最大值,我们可以边填表一边记录极值。
我们还可能遇到特殊情况,
比如:nums =[-3,-2,-3]
f表max=-2;
我们按照上面求得sum=-8,最小值也是-8。二者相见就是0。
二者比大小返回的是0,但是0是错误的。
我们需要特殊判断
代码实现
class Solution {
public:
int maxSubarraySumCircular(vector<int>& nums)
{
int sum=0;
for(auto&e:nums)
{
sum+=e;
}
int n=nums.size();
//建表
vector<int>f(n,0);
vector<int>g(n,0);
//初始化
f[0]=g[0]=nums[0];
//统计最大值,最小值
int fmax=nums[0];
int gmin=nums[0];
//填表
for(int i=1;i<n;i++)
{
f[i]=max(f[i-1]+nums[i],nums[i]);
g[i]=min(g[i-1]+nums[i],nums[i]);
fmax=max(fmax,f[i]);
gmin=min(gmin,g[i]);
}
//都是负数特殊处理
if(sum==gmin) return fmax;
return max(sum-gmin,fmax);
}
};
总结
以上就是我们对Leetcode详细介绍,希望对大家的学习有所帮助,仅供参考 如有错误请大佬指点我会尽快去改正 欢迎大家来评论~~