關於滑動窗口解決子串問題


目錄

滑窗思想:

滑窗編程範式:

力扣76:最小覆蓋子串

力扣438:找字符串中所有異位詞

力扣3:無重複最長子串:


 

滑窗思想:

在解決字符串子串問題時,可以採用滑窗的思想;

1,在字符串S中使用雙指針中左右指針技巧,初始化left = right = 0,把索引[left,right]成爲一個窗口

2,不斷增加right指針擴大窗口[left,right],直到窗口中字符串符合要求

3,停止增加right,同時不斷增加left縮小窗口,直到窗口中字符串不再符合要求,同時每增加一次left更新一輪結果

4,重複2-4直到right到達字符串S的勁頭。

 

滑窗編程範式:

// 滑窗思想解決字符串子串問題

int left = 0, right = 0;

while (right < s.size()) {
	window.add(s[right]);//滑動右邊界
	right++;

	while (valid) {		//滿足條件,滑動左邊界,
		window.remove(s[left]);
		left++;
}
}

 

力扣76:最小覆蓋子串

代碼實現:

class Solution {
public:
    string minWindow(string s, string t) {
        int start = 0,minLen = INT_MAX;
        int left = 0,right = 0;
        unordered_map<char,int>window;//統計窗內需要匹配的字母和頻次
        unordered_map<char,int>needs;//統計需要匹配的字母和頻次
        for(auto c:t)
            needs[c]++;
        int matchs = 0;//統計字母匹配結果,如window有5個g,needs有5個g則g匹配
        while(right<s.size())
        {
            char c1 = s[right];
            if(needs.count(c1))
            {
                window[c1]++;
                if(window[c1] == needs[c1])
                    matchs++;
            }
            right++;
            
            while(matchs == needs.size())
            {
                if(right - left<minLen)
                {
                    minLen = right - left;
                    start = left;
                }
                char c2 = s[left];
                if(needs.count(c2)){
                    window[c2]--;
                    if(window[c2] < needs[c2])
                        matchs--;
                }
                left++;
            }
            
        }
        return minLen == INT_MAX? "":s.substr(start,minLen);
    }
};

測試結果:

力扣438:找字符串中所有異位詞

代碼實現:

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
	vector<int>result;
	int left = 0, right = 0;
	int match = 0;
	unordered_map<char, int>needs;//記錄需要異位的字符和頻次
	unordered_map<char, int>window;//記錄窗裏面需要異位的字符及頻次
	for (auto c : p)
		needs[c]++;

	while (right < s.size())
	{
		char c1 = s[right];
		if (needs.count(c1))//判斷是不是需要異位的字母,進行窗記錄
		{
			window[c1]++;
			if (window[c1] == needs[c1])
			{
				match++;
			}
		}
		right++;
		while (match == needs.size())
		{
			if (right - left == p.size())//字母匹配後判斷長度匹配,否則可能窗內有多餘非異位字母
			{
				result.push_back(left);
			}
			char c2 = s[left];
			if (needs.count(c2))//判斷移除窗外的左邊界是否異位詞,更新window
			{
				window[c2]--;
				if (window[c2]<needs[c2])
					match--;
			}
			left++;
		}
	}
	return result;
}
};

測試結果:

力扣3:無重複最長子串:

代碼實現:

class Solution {
public:
   int lengthOfLongestSubstring(string s) {
	unordered_map<char, int>window;
	int left = 0, right = 0;
	int res = 0;
	while (right<s.size())
	{
		char c1 = s[right];
		window[c1]++;
		right++;
		while (window[c1]>1)//有邊界出現重複,移動左邊界直到不重複爲止;
		{
			char c2 = s[left];
			window[c2]--;
			left++;
		}
		res = max(res, right - left);
	}
	return res;
}
};

測試結果:

 

參考:

力扣高票解答:https://leetcode-cn.com/problems/minimum-window-substring/solution/hua-dong-chuang-kou-suan-fa-tong-yong-si-xiang-by-/

https://leetcode-cn.com/problems/minimum-window-substring/solution/zui-xiao-fu-gai-zi-chuan-by-leetcode-2/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章