2025年11月25日

2025年11月25日

一.滑动窗口专题:

image

image

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ans; // 记录满足条件的起点。
        //异位词就是不考虑字母顺序,所以只需要统计每个字符串内个字母个数,如果相同则是异位词
        array<int, 26> cnt_s;//统计s中子串
        array<int, 26> cnt_p;//统计p串,滑动窗口
        for (int i = 0; i < p.size(); i++) {
            cnt_p[p[i] - 'a']++;
        }
        for (int right = 0; right < s.size(); right++) { // 滑动窗口右边界
            int left = right - p.size() + 1;//左边界
            cnt_s[s[right] - 'a']++;
            if (left < 0) { // 窗口大小未达到p的大小
                continue;
            }
            if (cnt_p == cnt_s) {
                ans.push_back(left);
            }
            cnt_s[s[left] - 'a']--;//窗口满了就退出左边一格
        }
        return ans;
    }
};

用array不直接用数组例如int a[ ]因为不能直接比较两个数组是否一样,所以用array 

 

image

image

方法一:暴力-->超时

class Solution {

public:
    int lengthOfLongestSubstring(string s) {
        int n=s.size();
        vector<vector<bool>>flag;//flag[i][j]=true表示s[i->j]是无重复字符的,利用动态规划思想
     for(int i=0;i<n;i++){
        vector<bool>a;
        for(int j=0;j<n;j++){
            a.push_back(false);//默认都是重复字符
        }
        flag.push_back(a);
     }
        for(int i=0;i<n;i++){
            flag[i][i]=true;//单个字符一定不重复
        }
        int ans=0;
          for(int i=0;i<n;i++){
            for(int j=i;j<n;j++){
                bool f=true;
                for(int k=j-1;k>=i;k--){
                 if(s[k]==s[j]){
                    f=false;
                 }
                }
                //如果无重复就更新
                if(j==0)flag[i][j]=true;
       else if(flag[i][j-1]&&f==true)    flag[i][j]=true;
                if(flag[i][j]==true){//更新答案
                    ans=max(ans,j-i+1);
                }
            }
          }

        return ans;
    }
};

方法二:滑动窗口+哈希表

对于无重复字符串可采用哈希表数据结构!

 

class Solution {

public:
    int lengthOfLongestSubstring(string s) {
       unordered_set<char>a;//哈希表
       int ans=0;
       int right=-1;//右边界
       for(int i=0;i<s.size();i++){
           if(i!=0)   {
            a.erase(s[i-1]);//滑动窗口左边界向右收缩一格,从哈希表里删除s[i-1]
           }
           //以当前i为左边界,右边界right一直向右直到出现重复元素
           while(right+1<s.size()&&a.count(s[right+1])==0){
            a.insert(s[right+1]);
            right++;
           }
           ans=max(ans,right-i+1);
       }
       return ans;
    }
};

 

image

image

方法:优先队列+滑动窗口

快速获得最大值区间最大值多次获取使用优先队列priority_queue

priority_queue默认大根堆

3. 基本操作(5 个核心接口)

操作 功能描述 时间复杂度 注意事项
pq.push(val) 向队列中插入元素,并自动调整堆结构 O(log n) n 是当前队列元素个数
pq.pop() 删除堆顶元素(优先级最高的元素),自动调整 O(log n) 1. 不返回删除的元素;2. 空队列调用会崩溃
pq.top() 返回堆顶元素(优先级最高的元素) O(1) 空队列调用会崩溃,需先判断非空
pq.empty() 判断队列是否为空(空返回 true,否则 false) O(1) 访问 top() 或 pop() 前必须判断
pq.size() 返回队列中元素的个数 O(1) 用于循环遍历或边界判断
定义形式 说明 底层结构 优先级规则(堆类型)
priority_queue<int> pq; 默认形式(最常用) vector<int> 大根堆(最大值优先)
priority_queue<int, vector<int>, greater<int>> pq; 小根堆(最小值优先) vector<int> 小根堆(最小值优先)

 

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
       priority_queue<pair<int,int>>dl;//默认大根堆
       vector<int>ans;
       for(int i=0;i<k;i++){
        dl.push({nums[i],i});//队列里存放的pair数据类型
       }
        ans.push_back(dl.top().first);
        //滑动窗口,维持一个窗口大小为k的窗口
         for(int j=k;j<nums.size();j++){
            dl.push({nums[j],j});
            while(dl.top().second<=j-k){
                dl.pop();
            }
            ans.push_back(dl.top().first);
         }
         return ans;
    }
};

 

posted @ 2025-11-25 21:46  Annaprincess  阅读(3)  评论(0)    收藏  举报