1.长度最小的子数组
思路:
滑动窗口四步-》
1.进窗口
2.判断
3.出窗口
4.更新结果-》这个更新结果的位置就题而定
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int ret = INT_MAX, sum = 0;
for(int left = 0, right = 0; right < nums.size(); right++)
{
sum += nums[right]; //进窗口
while(sum >= target)//判断
{
ret = min(ret, right - left + 1);
sum -= nums[left++]; //出窗口
}
}
return ret == INT_MAX ? 0 : ret;
}
};
2.无重复字符的最长子串
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int hash[128] = { 0 };
int n = s.size();
int left = 0, right = 0, ret = 0;
while(right < n)
{
hash[s[right]]++;//进窗口
while(hash[s[right]] > 1)//判断
hash[s[left++]]--;//出窗口
ret = max(ret, right - left + 1);//更新结果
right++;
}
return ret;
}
};
3.最大连续1的个数
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int zero = 0;//记录0的个数
int ret = 0;
int n = nums.size();
if(k >= n) return n; // 处理细节问题
for(int left = 0, right = 0; right < n; right++)
{
if(nums[right] == 0) zero++;//进窗口
while(zero > k)
if(nums[left++] == 0) zero--;//出窗口
ret = max(ret, right - left + 1); //更新结果
}
return ret;
}
};
4.将x减到0的最小操作数
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
int len = -1, sum = 0, n = nums.size();
for(int i : nums) sum += i;//数组的和
int target = sum - x;
if(target < 0) return -1; //处理细节问题
for(int left = 0, right = 0, tmp = 0; right < n; right++)
{
tmp += nums[right]; //进窗口
while(tmp > target)//判断,不判断等于target的原因:等于就找到了我们要的结果,无需再出窗口
tmp -= nums[left++];//出窗口
if(tmp == target) //更新结果
len = max(len, right - left + 1);
}
if(len == -1) return len;
else return n - len;
}
};
5.水果成篮
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int hash1[26] = { 0 };//记录p中的字符出现个数
for(char ch : p) hash1[ch - 'a']++;
int hash2[26] = { 0 };//记录窗口内的字符出现个数
int m = p.size();
vector<int> ret;
for(int left = 0, right = 0, cnt = 0; right < s.size(); right++)
{
char in = s[right];//进窗口
if(++hash2[in - 'a'] <= hash1[in - 'a']) cnt++;//cnt用来记录窗口中出现有效字符的个数
if(right - left + 1 > m) //判断
{
//出窗口
char out = s[left++];
if(hash2[out - 'a']-- <= hash1[out - 'a']) cnt--;
}
if(cnt == m)
ret.push_back(left);//更新结果
}
return ret;
}
};
6.找到字符串中所有字母异位词
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int hash1[26] = { 0 };//记录p中的字符出现个数
for(char ch : p) hash1[ch - 'a']++;
int hash2[26] = { 0 };//记录窗口内的字符出现个数
int m = p.size();
vector<int> ret;
for(int left = 0, right = 0, cnt = 0; right < s.size(); right++)
{
char in = s[right];//进窗口
if(++hash2[in - 'a'] <= hash1[in - 'a']) cnt++;//cnt用来记录窗口中出现有效字符的个数
while(right - left + 1 > m) //判断
{
//出窗口
char out = s[left++];
if(hash2[out - 'a']-- <= hash1[out - 'a']) cnt--;
}
if(cnt == m)
ret.push_back(left);//更新结果
}
return ret;
}
};
7.串联所有单词的子串
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> ret;
unordered_map<string, int> hash1;//记录word字符串数组中有效字符串的个数
for(auto s : words) hash1[s]++;
unordered_map<string, int> hash2;//记录窗口中有效字符串的个数
int len = words[0].size(), n = words.size();
for(int i = 0; i < len; i++)//执行len次滑动窗口
{
for(int left = i, right = i, cnt = 0; right + len <= s.size(); right += len)
{
string in = s.substr(right, len);
if(++hash2[in] <= hash1[in]) cnt++;//进窗口,cnt记录窗口内有效字符串的个数
while(right - left + 1 > n * len) //判断
{
string out = s.substr(left, len);
if(hash2[out]-- <= hash1[out]) cnt--;//出窗口
left += len;
}
//更新结果
if(cnt == n)
ret.push_back(left);
}
}
return ret;
}
};
8.最小覆盖子串
class Solution {
public:
string minWindow(string s, string t) {
int hash1[128] = { 0 };//记录t中每个字符的频次
int kinds = 0;//记录t中有效字符的种类
for(char ch : t) if(hash1[ch]++ == 0) kinds++;
int hash2[128] = { 0 };//记录窗口中每个字符出现的频次
int minlen = INT_MAX, begin = -1;
for(int left = 0, right = 0, cnt = 0; right < s.size(); right++)
{
//进窗口
char in = s[right];
if(++hash2[in] == hash1[in]) cnt++;//cnt用来记录窗口内有效字符的种类
while(cnt == kinds)//判断是否符合条件
{
//更新结果
if(right - left + 1 < minlen)
{
minlen = right - left + 1;
begin = left;
}
char out = s[left++];
if(hash2[out]-- == hash1[out]) cnt--;//出窗口
}
}
if(begin == -1) return "";
else return s.substr(begin, minlen);
}
};