leetcode hot100(3)子串

560.和为K的子数组

cpp 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
       int n=nums.size();
       vector<int>pre(n);
       pre[0]=nums[0];
       for(int i=1;i<n;i++)
       {
        pre[i]=pre[i-1]+nums[i];
       }
       int ans=0;
       unordered_map<int,int>mp;
       int sum=0;
       mp[0]++;         //对应j=0,j-1为负的情况
       for(int i=0;i<n;i++)
       {
            sum+=(mp[pre[i]-k]);
             mp[pre[i]]++;
       }
       return sum;
    }
};

时间复杂度O(n)

思路:可以通过以i为数组右边界,依次列举左边界j并进行判断是否数组符合条件,时间复杂度为O(n二次方),其中i为有边界占用n次,向左枚举占用n次,判断使用前缀和O(1),预处理为O(n),故为O(n*n)+O(n)=O(n*n)

判断数组是否符合只需要prei-prej-1=k,即prej-1=prei-k,这里只需要知道多少个j能符合就行,可以用哈希表计数,优化为O(n),因为每次只需要i左侧的,故遍历i的过程中进行哈希表的更新即可。

239.滑动窗口最大值

cpp 复制代码
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>ans;
        deque<int>q;
        int n=nums.size();
        for(int i=0;i<k;i++)
        {
            while(!q.empty()&&nums[i]>=nums[q.back()]){
                q.pop_back();
            }
            q.push_back(i);
        }
        ans.push_back(nums[q.front()]);
        for(int i=k;i<n;i++){
            while(!q.empty()&&i-q.front()>=k){
                q.pop_front();
            }
            while(!q.empty()&&nums[i]>nums[q.back()]){
                q.pop_back();
            }
            q.push_back(i);
            ans.push_back(nums[q.front()]);
        }
        return ans;
    }
};

时间复杂度O(n)

思路:

取一个双端队列,内部存储的是nums内下标。

遍历nums数组,

(1)当滑动窗口未达到指定k值的时候,i直接尾插入队列,如果尾部值小于等于numsi时,因为i的有效空间比队列内的值更长(队列内的值都在i的前面,比如i在遍历到i=8的时候才脱离滑动窗口,队列内其他值在遍历到i=8之前就已经脱离),并且i的值大于等于尾部值,故尾部值对答案没有影响,可以直接pop。

(2)当滑动窗口达到指定k值的时候,尾部仍然照上方法处理即可保证队列内部存储顺序为从大到小。在此之外还需要考虑头部最大这个值是否在有效期内,不在即pop。

76.最小覆盖子串

cpp 复制代码
class Solution {
public:
    string minWindow(string s, string t) {
        int n1=s.size();
        int n2=t.size();
        vector<int>a(128);
        int need=n2;
        for(int i=0;i<n2;i++)
        {
            a[t[i]]++;
        }
        int left=0;
        int ans_l=0;
        int len=n1;
        bool flag=0;//判断是否存在符合条件子字符串
        for(int i=0;i<n1;i++)
        {
            a[s[i]]--;
            if(a[s[i]]>=0)   //递减之前需要这个字母
            {
                need--;
            }
            while(need==0)    //滑动数组左边界收缩
            {
                flag=1;
                if(i-left+1<len)
                {
                    len=i-left+1;
                    ans_l=left;
                }
                a[s[left]]++;
                if(a[s[left]]>0)  //不需要的字母右指针遍历的时候减去的和现在加上的抵消为0,故大于0则是需要覆盖的
                {
                    need++;
                }
                left++;
            }
        }
        if(flag==0)return "";
        string ans=s.substr(ans_l,len);
        return ans;
       
    }
};
​

时间复杂度O(m+n)

思路:

开一个128的数组,存t中所有字母的出现次数,记录t中字母个数need,滑动窗口向右扩展每次出现t中字母的时候need就--,需要的这个字母次数也--(可以为负数,说明这个窗口中这个字母数量多),当need等于0的时候这个滑动窗口覆盖了字符串t,左边界就可以向右压缩得到尽可能短的子串。

左边界向右压缩过程,字母次数++后只有在这个字母需要次数大于0才need++,因为如果初始的时候t没有这个字母即at\[i]=0,那么在向右扩展和左边界向右压缩的过程这个值都不会大于0,大于0就代表这个字母是t中所需要的。

相关推荐
Black蜡笔小新7 分钟前
自动化AI算法训练服务器DLTM训推一体化平台助力农业生产管理实现安全智能化
人工智能·算法·自动化
8Qi81 小时前
LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)
数据结构·算法·leetcode·链表·
QiLinkOS1 小时前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源
Irissgwe2 小时前
c++STL--string类
c++·stl·string
松间听晚2 小时前
Agentic RL 环境和代码学习:以HGPO为例
算法
Irissgwe2 小时前
c++类型转换
c++·类型转换·explicit·static_cast·const_cast·dynamic_cast·rtti
智者知已应修善业2 小时前
【51单片机用T0定时器方式1,实现0.5S的时间间隔实现第一次一个灯亮、第二次二个灯亮,直到全部灯亮,然后重复整个过程】2023-12-29
c++·经验分享·笔记·算法·51单片机
小许同学记录成长2 小时前
几何体编辑与布尔运算
算法·无人机
fanged2 小时前
简单看看3A算法2(TODO)
算法
智者知已应修善业2 小时前
【51单片机4位静态数码管显示1234】2023-11-14
c++·经验分享·笔记·算法·51单片机