力扣刷题——2516. 每种字符至少取 K 个
一开始想的很简单,觉得在数组两端维护两个下标,用贪心的方法模拟取数字。
class Solution {
public:
int takeCharacters(string s, int k) {
int left = 0, right = s.size() - 1;
if(k == 0)
return 0;
int res = 0;
vector<int> tb(3, k);
while(left <= right)
{
if(tb[s[left] - 'a'])
{
tb[s[left] - 'a']--;
left++;
}
else if(tb[s[right] - 'a'])
{
tb[s[right] - 'a']--;
right--;
}
else
{
left++;
right--;
}
if(tb[0] == 0 && tb[1] == 0 && tb[2] == 0)
return res + 1;
res++;
}
return -1;
}
};
但这样会WA,因为在取数字的时候没有办法事先知道最优解是优先取右还是取左。
比如s ="cbbac" k=1
这个用例,代码是优先选左,最终得到的答案是4,但实际上这个用例是优先选右的。
既然维护选的方法不行,那么可以试试维护一个不选的滑动窗口。详细的做法是,从一开始就维护一个窗口,当排除掉这个窗口中的字母能够满足题目条件时,就输出一个答案跟之前的做比较,这样能取到所有的可能答案。
class Solution {
public:
int takeCharacters(string s, int k) {
int left = 0, right = s.size() - 1;
if(k == 0)
return 0;
int res = 0;
vector<int> tb(3, k);
while(left <= right)
{
if(tb[s[left] - 'a'])
{
tb[s[left] - 'a']--;
left++;
}
else if(tb[s[right] - 'a'])
{
tb[s[right] - 'a']--;
right--;
}
else
{
left++;
right--;
}
if(tb[0] == 0 && tb[1] == 0 && tb[2] == 0)
return res + 1;
res++;
}
return -1;
}
};