【算法】【字符串】Leetcode滑动窗口相关题目

滑动窗口

维护一个窗口,不断滑动;

for(int l = 0, r = 0; r < s.size();)
{
      //增大窗口
      win.add(s[r]);
      r++;

      //窗口右移
      while(满足某个条件)
      {
            win.remove(s[l]);
            l++;
            //更新某个值
      }
}

模板

void slidingWin(string str, string t)
{
	unordered_map<int, int> hashmap, win;
	
	for(char c : t) hashmap[c]++;
	
	int valid = 0;
	for(int l = 0, r = 0; r < str.size();)
	{
		//扩大窗口
		char ch = str[r];
		//窗口右移
		r++;
		
		//进行窗口内数据的一系列更新
		...
		
		
		cout << l << " " << r << endl;
		
		//移动窗口
		while()
		{
			//d是即将要移动出窗口的字符
			char d = str[l];
			//左移窗口
			l++;
			
			//更新结果
            ...
		}
	}
}

无重复字符的最长子串

题目链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> hashmap;

        int cnt = 0;
        for(int i = 0, j = 0; j < s.size(); j++)
        {
            hashmap[s[j]]++;
            while(hashmap[s[j]] > 1) hashmap[s[i++]]--;
            cnt = max(cnt, j - i + 1);
           
        }
        return cnt;
    }
};

最小覆盖子串

题目链接:https://leetcode-cn.com/problems/minimum-window-substring/

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> need, win;
        for(int i = 0; i < t.size(); i++) need[t[i]]++;

        //l和r分别是在当前字符串上维护的窗口的左右两端
        int l = 0, r = 0;
        int valid = 0;

        //记录最小子串的起始位置和长度
        int start = 0, cnt = INT_MAX;
       
        
        while(r < s.size())
        {
            //即将进入窗口的字符
            char ch = s[r];
            //右移窗口
            r++;

            //进行窗口内数据的一系列更新
            if(need.count(ch))
            {
                win[ch]++;
                if(win[ch] == need[ch]) valid++;
            }

            //判断左侧窗口是否要收缩
            while(valid == need.size())
            {
                //更新最小覆盖子串
                if(r - l < cnt)
                {
                    start = l;
                    cnt = r - l;
                }
                //向右滑动
                char d = s[l];
                l++;
                if(need.count(d))
                {
                    if(win[d] == need[d])
                        valid--;
                    win[d]--;
                }
            }
        }
        return cnt == INT_MAX ? "" : s.substr(start, cnt);


    }
};

字符串的排列

题目链接:https://leetcode-cn.com/problems/permutation-in-string/

class Solution {
public:
    bool checkInclusion(string s1, string s2) {

        //维护一个窗口为s1.size的窗口,判断s1中是否包含s1的所有
        unordered_map<int, int> hashmap, win;
        for(char c : s1) hashmap[c]++;
        
        int valid = 0;
        for(int l = 0, r = 0; r < s2.size();)
        {
            //扩大窗口
            char ch = s2[r];
            //窗口右移
            r++;
            
            //进行窗口内数据的一系列更新 更新判断条件valid
            //...
            if(hashmap.count(ch))
            {
                win[ch]++;
                if(win[ch] == hashmap[ch]) valid++;
            }
            
            cout << l << " " << r << endl;
            
            //移动窗口 满足条件了进行更新  包含那个字符
            while(r - l >= s1.size())
            {
                if(valid == hashmap.size()) return true;
                //d是即将要移动出窗口的字符
                char d = s2[l];
                //左移窗口
                l++;
                
                //更新结果
                //...
                if(hashmap.count(d))
                {
                    if(win[d] == hashmap[d])
                        valid--;
                    win[d]--;
                }
            }
        }
        return false;
    }
};

找到字符串中所有字母异位词

题目链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> res;

        unordered_map<char, int> hashmap, win;

        for(auto ch : p) hashmap[ch]++;

        int valid = 0;
        for(int l = 0, r = 0; r < s.size();)
        {
            char ch = s[r];
            r++;

            if(hashmap.count(ch))
            {
                win[ch]++;
                if(win[ch] == hashmap[ch]) valid++;
            }
            cout << l <<" " << r << " " << valid << endl;
            while(r - l >= p.size())
            {
                if(valid == hashmap.size()) res.push_back(l);

                char d = s[l];
                l++;
                if(hashmap.count(d))
                {
                    if(win[d] == hashmap[d]) valid--;
                    win[d]--;
                }
            }
        }
        return res;
    }
};
原文地址:https://www.cnblogs.com/Trevo/p/13517718.html