【算法】【字符串】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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章