4.同向双指针--滑动窗口
在上一篇博客双指针常用方法_绿风天空的博客-CSDN博客中,写到了同方向双指针快慢指针的用法,这一篇写另一个用法:滑动窗口。
力扣https://leetcode.cn/problems/minimum-window-substring/题目中要找满足包含满足条件的最小子串,所以可以用左右两个指针,右指针保证满足条件(包含字符串t的全部字符),左指针保证是最小子串。左右指针之间的范围就是滑动窗口。
先用长度128的两个vector记录字符串t的出现字符和出现频次。
接着在字符串s中从头开始移动右指针,每当滑动窗口中包含了字符串t的全部字符,就开始移动左指针,缩小滑动窗口范围。当然这可能会导致滑动窗口无法包含字符串t的全部字符,所以继续移动右指针,直至满足条件。
每次滑动窗口包含字符串t的全部字符都记录下最小长度,当右指针遍历完成时,就可以获得满足条件的最小子串。
代码:
class Solution {
public:
string minWindow(string s, string t) {
int m = s.size(), n = t.size();
vector<int> record(128,0);
vector<bool> flag(128,false);
for(auto c: t){
flag[c] = true;
record[c]++;
}
int k=0, left = 0, minLen = m +1, minLeft;
for(int right=0;right<m;right++){
if(flag[s[right]]){
if(--record[s[right]] >=0 ){
k++;
}
}
while(k==n){
if((right-left+1)<minLen){
minLen = right-left+1;
minLeft = left;
}
if(flag[s[left]] && ++record[s[left]]>0 ){
k--;
}
left++;
}
}
return minLen==m+1?"":s.substr(minLeft,minLen);
}
};
5.更多练习题
力扣https://leetcode.cn/problems/longest-word-in-dictionary-through-deleting/这题先对字典排序,再依次遍历字典,用两个指针分别指向s和字典内字符串。
class Solution {
public:
string findLongestWord(string s, vector<string>& dictionary) {
sort(dictionary.begin(), dictionary.end(),
[&](string& a, string& b){
if(a.size()==b.size()){
return a<b;
}
return a.size() > b.size();
}
);
for(auto d :dictionary){
if(judge(s,d)){
return d;
}
}
return "";
}
bool judge(string s, string d){
int m = s.size(), n = d.size();
int i = 0, j = 0;
while(i<m && j<n){
if(s[i]==d[j]){
j++;
}
i++;
}
return j==n;
}
};