题目来源
分享丨【题单】滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环) - 力扣(LeetCode)
209. 长度最小的子数组 - 力扣(LeetCode)
题目要求大于等于
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int left=0, right=0;
int miniLen=n+1;
int temCnt=0;
for(right=0;right<n;right++){
temCnt+=nums[right];
while(temCnt>=target){
miniLen = min(miniLen,right-left+1);
temCnt-=nums[left];
left++;
}
}
return miniLen==n+1?0:miniLen;
}
};
2904. 最短且字典序最小的美丽子字符串 - 力扣(LeetCode)
substr(起始下标,长度)
class Solution {
public:
string shortestBeautifulSubstring(string s, int k) {
int len = s.length();
int cnt=0, left=0, right=0, minLen = len+1;
string result;
for(right=0;right<len;right++){
if(s[right]=='1') cnt++;
//尝试缩小窗口
while(cnt==k){
int currentLen = right-left+1;
if(currentLen<minLen){
minLen = currentLen;
result = s.substr(left,minLen);
}else if(currentLen==minLen){
//比较字典序
string temStr = s.substr(left,currentLen);
if(temStr<result) result = temStr;
}
if(s[left]=='1') cnt--;
left++;
}
}
return result;
}
};
1234. 替换子串得到平衡字符串 - 力扣(LeetCode)
滑动窗口内的就是要替换的,如果窗口外的值都<=target,就可以尝试缩小窗口
(为什么是<=target)
class Solution {
public:
int balancedString(string s) {
unordered_map<char,int> charCnt;
int len = s.length();
int target = len/4;
int left=0, right=0;
int minLen=len+1;
for(char c:s){
charCnt[c]++;
}
if(charCnt['Q']==target && charCnt['W']==target && charCnt['E']==target && charCnt['R']==target){
return 0;
}
for(right=0;right<len;right++){
charCnt[s[right]]--;
while(charCnt['Q']<=target && charCnt['W']<=target && charCnt['E']<=target && charCnt['R']<=target){
minLen = min(minLen,right-left+1);
charCnt[s[left]]++;
left++;
}
}
return minLen;
}
};
2875. 无限数组的最短子数组 - 力扣(LeetCode)
下面题解解释了为什么只用重复一次nums
class Solution {
public:
int minSizeSubarray(vector<int>& nums, int target) {
vector<int> numsVec;
int len = nums.size();
long long totalNum=0;
for(int num : nums){
totalNum += num;
}
if(totalNum == target) return len;
int k = target / totalNum;
int lateNum = target % totalNum;
int left=0, right=0;
long long cnt=0;
int minLen=INT_MAX;
numsVec = nums;
numsVec.insert(numsVec.end(),nums.begin(),nums.end());
// numsVec = nums+nums;
for(right=0;right<2*len;right++){
cnt += numsVec[right];
while(cnt > lateNum){
cnt -= numsVec[left];
left++;
}
if(cnt == lateNum){
minLen = min(minLen,right-left+1);
}
}
return minLen == INT_MAX?-1:minLen +k*len;
}
};
76. 最小覆盖子串 - 力扣(LeetCode)
set<char> uniqueChars(charRe.begin(),charRe.end()); //去重
charRe.assign(uniqueChars.begin(),uniqueChars.end());
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char,int> charCnt;
unordered_map<char,int> charNow;
int len = s.length();
int left=0, right=0;
int minLen=INT_MAX;
int required=0, formed=0;
int start=0;
for(char c:t){
charCnt[c]++;
}
required = charCnt.size();
for(right=0;right<len;right++){
char c = s[right];
charNow[c]++;
if(charCnt.count(c) && charCnt[c]==charNow[c]){
formed++;
}
while(right>=left && required == formed){
//试图缩小窗口
if(right-left+1<minLen){
minLen = min(minLen,right-left+1);
start = left;
}
if(charCnt.count(s[left]) && charNow[s[left]]==charCnt[s[left]]){
formed--;
}
charNow[s[left]]--;
left++;
}
}
return minLen==INT_MAX?"":s.substr(start,minLen);
}
};
新方法
charCnt.count(c)检查在不在
然后用formed看是否找全了
减的时候还要formed--;
还有right>=left(暂时没有很理解)