给你一个由字符 '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.先统计字符出现的次数要大于等于k的值,否则返回-1
代码:
// 计数数组,初始化
int[] cnt = new int[3];
int n = s.length();
int ans = 0;
// 统计每个字符的出现次数
for (int i = 0; i < n; i++) {
cnt[s.charAt(i) - 'a']++;
}
// 检查每个字符的计数是否满足小于 k 的条件
if (cnt[0] < k || cnt[1] < k || cnt[2] < k) {
return -1; // 如果任一字符的计数小于 k,返回 -1
}
2.滑动窗口算法,用于找到满足条件的最短子串,并更新结果 ans,找到最短的子串(即可以删除的最大字符长度)
完整代码:
class Solution {
public int takeCharacters(String s, int k) {
// 计数数组,用于统计每个字符的出现次数
int[] cnt = new int[3];
// 字符串长度
int len = s.length();
// 初始化答案为字符串长度,后续会取最小值
int ans = len;
// 遍历字符串,统计每个字符的出现次数
for (int i = 0; i < len; i++) {
cnt[s.charAt(i) - 'a']++;
}
// 如果任一字符的计数小于k,无法满足条件,返回-1
if (cnt[0] < k || cnt[1] < k || cnt[2] < k) {
return -1;
}
// 左指针,用于滑动窗口
int l = 0;
// 右指针,用于滑动窗口
for (int r = 0; r < len; r++) {
// 移除当前字符,因为考虑的是移除字符的情况
cnt[s.charAt(r) - 'a']--;
// 当左指针小于右指针,并且存在字符计数小于k时,调整左指针位置
while (l < r && (cnt[0] < k || cnt[1] < k || cnt[2] < k)) {
// 将左指针指向的字符计数加回
cnt[s.charAt(l) - 'a']++;
// 左指针右移
l++;
}
// 如果满足每个字符至少出现k次的条件,更新答案
if (cnt[0] >= k && cnt[1] >= k && cnt[2] >= k) {
ans = Math.min(ans, len - (r - l + 1));
}
}
// 返回最终答案
return ans;
}
}
标签:字符,每种,int,cnt,++,ans,2516,指针
From: https://www.cnblogs.com/java-cheng/p/18438979