一、力扣904——水果成篮
题目解析:
这道题说的是我们有两个篮子,一个篮子只能装一种水果,再给出的示例中,
fruits = [1,2,3,2,2]
数字1是一种水果,数字2是一种水果,数字3是一种水果,我们只能取两种水果,怎么取最多,并输出一共可以摘多少水果数量。
我这里我们用滑动窗口算法解决,定义两个指针left和right从左往右滑动,right负责进窗口,left负责出窗口,那什么时候出窗口呢?
我们知道只有两个篮子,说明只能装两种类型的水果,就如这个例子
fruits = [0,1,2,2]
class Solution {
public:
int totalFruit(vector<int>& fruits) {
unordered_map<int,int> hash;
int left = 0,right = 0;
int ret = 0;
int size = fruits.size();
while(right < size)
{
hash[fruits[right]]++; //进窗口
while(hash.size() > 2)
{
//出窗口
hash[fruits[left]]--;
if(hash[fruits[left]] == 0)
{
hash.erase(fruits[left]);
}
left++;
}
ret = std::max(ret,right - left + 1);
right++;
}
return ret;
}
};
上面说了right负责进窗口,right把所指向的这个值存放到hash表中,当right指向2的时候,两个篮子分别装的是0和1,所以此时不能再装了,也就是hash.size() >2是出窗口条件,这个时候left就要右移了
但如果是这种情况,left右移两个篮子依然装着两种水果,所以我们这里用的是while判断条件
根据这个逻辑从左往右依次遍历,找出两种水果最长的。
代码如下:
class Solution {
public:
int totalFruit(vector<int>& fruits) {
unordered_map<int,int> hash;
int left = 0,right = 0;
int ret = 0;
int size = fruits.size();
while(right < size)
{
hash[fruits[right]]++; //进窗口
while(hash.size() > 2)
{
//出窗口
hash[fruits[left]]--;
if(hash[fruits[left]] == 0)
{
hash.erase(fruits[left]);
}
left++;
}
ret = std::max(ret,right - left + 1);
right++;
}
return ret;
}
};
二、力扣438——找到字符串中所有字母异位词 
题目解析
看到这道题可能会想,什么是异位词,举个例子abc,那它的异位词是
就是a、b、c排列组合,题目中就是让我们找到abc的异位词,并返回起始的索引
这道题我们先用数组记录下p中所有字符,
再定义一个有效字符count,我们依然使用滑动窗口,在s字符串中定义left和right,right一直往右遍历,并把每一个字符放入s所对应的hash数组中,
当hash2[in - 'a'] <= hash1[in - 'a'],就代表者滑动窗口内存在一个有效字符
我们拿这个举例,left和right都先指向c
进入判断的时候,c是hash1中的有效字符,所以count++
那什么时候出窗口呢?
当滑动窗口这个窗口的大小大于abc.size()的时候,left就要右移了
此时我们要判断left右移的时候,滑出窗口的那个字符是不是有效字符
最后判定条件是count == p.size()
代码如下:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int hash1[26] = {0};
vector<int> v1;
for(auto ch:p)
{
hash1[ch - 'a']++;
}
int hash2[26] = {0};
int m = p.size();
for(int left = 0,right = 0,count = 0;right < s.size();right++)
{
//进窗口
char in = s[right];
hash2[in - 'a']++;
if(hash2[in - 'a'] <= hash1[in - 'a']) count++;
//出窗口
if(right - left + 1 > m)
{
char out = s[left];
if(hash2[out - 'a'] <= hash1[out - 'a']) count--;
hash2[out - 'a']--;
left++;
}
if(count == m) v1.push_back(left);
}
return v1;
}
};
三、力扣30——串联所有单词的字串
题目解析,这道题其实跟上一道题找到字符串中所有字母异位词是一样的,我们可以把words数组里的每一个字符串当作整体,进行排列组合,再把s中的整体字符串拆分为words子字符串的大小。例如words子字符串大小是3,我们将s字符串可以拆分成bar、foo、foo、bar、the、foo、bar、man。
整体思路其实是跟上一题一样的
但这题还是有部分细节是不同的,当我们写完目前思路代码再继续给大家看
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
unordered_map<string,int> hash1;
vector<int> v1;
for(auto e:words)
{
hash1[e]++;
}
int m = words.size();
int len = words[0].size();
unordered_map<string,int> hash2;
for(int left = 0,right = 0,count = 0;right < s.size();right += len)
{
//进窗口
string in = s.substr(right,len);
hash2[in]++;
if(hash2[in] <= hash1[in]) count++;
//出窗口
if(right - left + 1 > m*len)
{
string out = s.substr(left,len);
if(hash2[out] <= hash1[out]) count--;
hash2[out]--;
left += len;
}
if(count == m)
{
v1.push_back(left);
}
}
return v1;
}
};
这一份代码目前的测试用例都能够,当我们提交一下会发生这样的报错
我们将s字符串以4个单位一一划分就知道了,所以我们还要加一个循环
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
unordered_map<string,int> hash1;
vector<int> v1;
for(auto e:words)
{
hash1[e]++;
}
int m = words.size();
int len = words[0].size();
for(int i = 0;i < len;i++)
{
unordered_map<string,int> hash2;
for(int left = i,right = i,count = 0;right < s.size();right += len)
{
//进窗口
string in = s.substr(right,len);
hash2[in]++;
if(hash2[in] <= hash1[in]) count++;
//出窗口
if(right - left + 1 > m*len)
{
string out = s.substr(left,len);
if(hash2[out] <= hash1[out]) count--;
hash2[out]--;
left += len;
}
if(count == m)
{
v1.push_back(left);
}
}
}
return v1;
}
};
四、力扣76——最小覆盖字串
这道题是让我们在s字符串中找到包含t的最小子字符串
这道题我在之前的博客讲了一遍,具体思路也不细讲了
class Solution {
public:
string minWindow(string s, string t) {
int hash1[128] = {0};
int hash2[128] = {0};
int kind = 0;
for(auto ch:t)
{
if(hash1[ch] == 0)
{
kind++;
}
hash1[ch]++;
}
int minlen = INT_MAX,begin = -1;
for(int left = 0,right = 0,count = 0;right < s.size();right++)
{
//进窗口
char in = s[right];
hash2[in]++;
if(hash2[in] == hash1[in]) count++;
while(count == kind)
{
if(right - left + 1 < minlen)
{
minlen = right - left + 1;
begin = left;
}
//出窗口
char out = s[left];
if(hash2[out] == hash1[out]) count--;
hash2[out]--;
left++;
}
}
if(begin == -1)
{
return "";
}
else
{
return s.substr(begin,minlen);
}
}
};