【演算法】【字串】Leetcode滑動視窗相關題目
阿新 • • 發佈:2020-08-22
滑動視窗
維護一個視窗,不斷滑動;
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;
}
};