LeetCode刷题笔记-动态规划-day5
53. 最大子数组和
1.题目2.解题思路3.代码 918. 环形子数组的最大和
1.题目2.解题思路3.代码
LeetCode刷题笔记-动态规划-day5 53. 最大子数组和 1.题目2.解题思路原题链接:53. 最大子数组和
算法:前缀和
- 我们用一个sum变量表示遍历到当前位置数组的前缀和用minn变量表示遍历到当前位置,前面所有位置前缀和的最小值遍历过程中答案需要更新,应该等于:res=max(res,sum-minn);
class Solution {
public:
int maxSubArray(vector& a) {
int res=-1e9;
int sum=0,minn=1e9;
for(int i=0;i
918. 环形子数组的最大和
1.题目
原题链接:918. 环形子数组的最大和
2.解题思路
算法:单调栈+前缀和
因为这是一个环形的数组,一般我们在做环形的题目的时候,都会将其变成长度为环形长度两部的数组,只需要维护中间一段长度为n的数组,这样就等价于环形问题。对转换的数组求前缀和然后维护一个单调队列,这里用deque维护,队头维护的是最小前缀和的下标每次更新需要检查队内元素是否多余n个,多余的话队头元素出队每次更新答案: res=max(res,s[i]-s[q.front()]);每次入队需要将当前队尾前缀和大于当前入队下标前缀和的元素删除每次遍历结束,入队
3.代码
class Solution {
public:
int maxSubarraySumCircular(vector& a) {
int n=a.size();
vector s(2*n+1);
for(int i=1;i<=2*n;i++){
s[i]+=s[i-1]+a[(i-1)%n];
}
int res=-1e9;
deque q;
q.push_back(0);
for(int i=1;i<=2*n;i++){
while(q.size()&&i-q.front()>n) q.pop_front();
res=max(res,s[i]-s[q.front()]);
while(q.size()&&s[i]<=s[q.back()]) q.pop_back();
q.push_back(i);
}
return res;
}
};



