【002】2516. 每种字符至少取 K 个【滑动窗口+逆向思维】

每种字符至少取 K 个

给你一个由字符 ‘a’、‘b’、‘c’ 组成的字符串 s 和一个非负整数 k 。每分钟,你可以选择取走 s 最左侧 还是 最右侧 的那个字符。
你必须取走每种字符 至少 k 个,返回需要的 最少 分钟数;如果无法取到,则返回 -1 。

https://leetcode.cn/problems/take-k-of-each-character-from-left-and-right/description/

  1. 滑动窗口:保证窗口之外三种字母至少有k个。记录窗口最大值。
  2. 字符串中元素个数:str.length()-str.replace(b,"").length()++counts[s.charAt(i) - 'a']
  3. 最少次数=字符串长度-滑动窗口最大值
import java.util.HashMap;
import java.util.Map;

class Solution {
    public static void main(String[] args) {
        String str = "aabaaaacaabc";
        int k = 2;
        System.out.println(takeCharacters(str, k));
    }

    /**
     *
     * @param s 待处理字符串
     * @param k 字母重复次数
     * @return 最少操作次数
     */
    public static int takeCharacters(String s, int k) {
        Map<Character, Integer> map = new HashMap<>();
        map.put('a', s.length() - s.replace("a", "").length());
        map.put('b', s.length() - s.replace("b", "").length());
        map.put('c', s.length() - s.replace("c", "").length());

        if (map.get('a') < k || map.get('b') < k || map.get('c') < k) {
            return -1;
        }

        int maxTake = 0;
        int left = 0;
        for (int right = 0; right < s.length(); right++) {
            map.put(s.charAt(right), map.get(s.charAt(right)) - 1);
            if (map.get('a') < k || map.get('b') < k || map.get('c') < k) {
                map.put(s.charAt(left), map.get(s.charAt(left)) + 1);
                left++;
            } else {
                maxTake = Math.max(maxTake, right - left + 1);
            }
        }
        return s.length() - maxTake;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值