开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
至多包含两个不同字符的最长子串(leetcode-159) 会员题目!
和上面的做法完全一样!
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string &s) {
// Write your code here
unordered_map<char,int> map;//字符-在[left,right]范围内出现次数
int left = 0,right = 0;
int valid = 0;//当前[left,right]字符种类数
int res = 0;//最长子串的长度
for(right = 0;right<s.size();right++)
{
char ch = s[right]; //当前字符
if(map[ch] == 0)//当前字符在[left,right]范围内没有出现过
{
valid++;//种类++
}
map[ch]++;
//考察[left,right]的字符
//如果字符种类>2,从窗口左边弹出left指向的字符,直到满足字符种类<=2
while(valid>2)
{
char ch = s[left++]; //left往后走,该字符在[left,right]范围的出现次数--
if(--map[ch] == 0)
{
valid--;
}
}
//此时[left,right]的字符就是满足规则的,长度为:right-left+1
res = max(res,right-left+1);
}
return res;
}
};
注意:虽然使用了哈希表,但是这里的空间复杂度是O(1),因为哈希表里只包含不超过 3 个元素
[1700. 无法吃午餐的学生数量]
我们知道学生如果拿不到喜欢的三明治会再排队,这样一直循环往复,顺序就会改变,也就是是说这道题中学生的顺序不重要,而三明治的类型是不能变的,所以三明治的顺序很重要 ,学生位置可调整,而三明治位置不可调整
现在考虑拿不到三明治的情况:如果最上面的三明治是 0 ,但是没有喜欢 0 类型三明治的学生了,那么这个三明治就会卡住剩下的喜欢 1 的学生, 同理,最上面的三明治是1也可以卡住,若前面的三明治没被拿走,则往后的所有三明治也无法被拿走
所以我们只需要先求得喜欢两种类型的三明治的学生的人数,然后当最上层是某类型的三明治时,如果没有喜欢该类型三明治的学生了,就卡住了,剩下的就是喜欢另一种三明治的学生了,这些学生拿不走这个不同类型的三明治了,就吃不上饭了
做法: 我们先开辟一个只有两个空格的数组cnt,统计学生喜欢的三明治种类和对应的数量,然后遍历三明治,若在 cnt 中找不到喜欢此三明治的学生,说明当前及往后的三明治均无法被拿走, 如果找到了,就把该数量对应--, 最后返回当前cnt数组中学生喜欢的三明治种类和对应的数量,就是没有吃上的学生数量
class Solution {
public:
int countStudents(vector<int>& students, vector<int>& sandwiches) {
int cnt[2] = {0};//存储的是两种三文治的需求量,统计学生喜爱0 或者 1的数量
for(auto& student :students) //学生的需求
{
cnt[student]++;
}
//遍历三文治数组
for(auto& sandwiche :sandwiches)
{
if(cnt[sandwiche]>0) //某个学生拿走这个三文治
cnt[sandwiche]--;
else //否则当前三明治所有学生都不喜欢,即栈顶三明治没有学生喜欢
break; //结束流程
}
return cnt[0]+cnt[1];//返回当前两种三明治的需求量也就是无法吃午餐学生的数量
}
};