LeetCode刷题笔记-动态规划-day5

LeetCode刷题笔记-动态规划-day5

53. 最大子数组和

1.题目

原题链接:53. 最大子数组和

image-20220209103112734

2.解题思路

算法:前缀和

  1. 我们用一个sum变量表示遍历到当前位置数组的前缀和
  2. minn变量表示遍历到当前位置,前面所有位置前缀和的最小值
  3. 遍历过程中答案需要更新,应该等于:res=max(res,sum-minn);

3.代码

class Solution {
    
    
public:
    int maxSubArray(vector<int>& a) {
    
    
        int res=-1e9;
        int sum=0,minn=1e9;
        for(int i=0;i<a.size();i++){
    
    
            minn=min(minn,sum);
            sum+=a[i];
            res=max(res,sum-minn);
        }
        return res;
    }
};

918. 环形子数组的最大和

1.题目

原题链接:918. 环形子数组的最大和

image-20220209103042790

image-20220209103052054

2.解题思路

算法:单调栈+前缀和

  1. 因为这是一个环形的数组,一般我们在做环形的题目的时候,都会将其变成长度为环形长度两部的数组,只需要维护中间一段长度为n的数组,这样就等价于环形问题。
  2. 对转换的数组求前缀和
  3. 然后维护一个单调队列,这里用deque维护,队头维护的是最小前缀和的下标
  4. 每次更新需要检查队内元素是否多余n个,多余的话队头元素出队
  5. 每次更新答案: res=max(res,s[i]-s[q.front()]);
  6. 每次入队需要将当前队尾前缀和大于当前入队下标前缀和的元素删除
  7. 每次遍历结束,入队

3.代码

class Solution {
    
    
public:
    int maxSubarraySumCircular(vector<int>& a) {
    
    
            int n=a.size();
            vector<int> 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<int> 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;
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45966440/article/details/122875133
今日推荐