2516. 每种字符至少取 K 个

发布时间 2023-04-02 16:46:46作者: Co3y

力扣题目链接

给你一个由字符 'a''b''c' 组成的字符串 s 和一个非负整数 k 。每分钟,你可以选择取走 s 最左侧 还是 最右侧 的那个字符。

你必须取走每种字符 至少 k 个,返回需要的 最少 分钟数;如果无法取到,则返回 -1 。

 

示例 1:

输入:s = "aabaaaacaabc", k = 2
输出:8
解释:
从 s 的左侧取三个字符,现在共取到两个字符 'a' 、一个字符 'b' 。
从 s 的右侧取五个字符,现在共取到四个字符 'a' 、两个字符 'b' 和两个字符 'c' 。
共需要 3 + 5 = 8 分钟。
可以证明需要的最少分钟数是 8 。

示例 2:

输入:s = "a", k = 1
输出:-1
解释:无法取到一个字符 'b' 或者 'c',所以返回 -1 。

 

提示:

  • 1 <= s.length <= 10^5
  • s 仅由字母 'a''b''c' 组成
  • 0 <= k <= s.length
 1 class Solution {
 2     public int takeCharacters(String s, int k) {
 3         int len = s.length();
 4         if (len < 3 * k)
 5             return -1;
 6         int[] arr = new int[3];
 7         char[] cs = s.toCharArray();
 8         for (char c : cs) {
 9             arr[c - 'a']++;
10         }
11         //needA、needB、needC是剩下的a,b,c的个数,即中间的最长连续子序列需要的个数。
12         int needA = arr[0] - k;
13         int needB = arr[1] - k;
14         int needC = arr[2] - k;
15         if (needA == 0 && needB == 0 && needC == 0)
16             return len;
17         if (needA < 0 || needB < 0 || needC < 0)
18             return -1;
19         //至此将原题转化为求中间剩下的最长连续子序列的长度是多少,最后用总长度减去即为解。
20         arr = new int[3];
21         int left = 0, right = 0;
22         int maxLen = 0;
23         while (right < len) {
24             char r = cs[right];
25             right++;
26             arr[r - 'a']++;
27             while (arr[0] > needA || arr[1] > needB || arr[2] > needC) {
28                 char l = cs[left];
29                 left++;
30                 arr[l - 'a']--;
31             }
32             maxLen = Math.max(maxLen, right - left);
33         }
34         return len - maxLen;
35     }
36 }