力扣刷题——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;
    }
};
posted @ 2024-09-29 10:48  SuzumiyaYui  阅读(5)  评论(0编辑  收藏  举报