问题描述
思路分析
1. 分析问题
- 组成条件:每个 “ku” 需要 1 个
k
和 1 个u
。 - 约束条件:从字符串中选择的字符不能重复使用。
- 目标:在给定字符串中,找到
k
和u
的数量,取其较小值作为结果,因为这是限制组成 “ku” 数量的瓶颈。
2. 分解问题
解决问题可以分为以下几个步骤:
-
统计字符频率:
- 遍历字符串,统计
k
和u
的出现次数。 - 为了处理大小写,所有字符统一转换为小写或直接通过判断
char
忽略大小写。
- 遍历字符串,统计
-
计算限制条件:
- 每次组成一个 “ku”,需要同时消耗一个
k
和一个u
。 - 如果
k
的数量大于u
,那么能组成的 “ku” 取决于u
的数量,反之亦然。 - 因此结果是
min(出现次数k, 出现次数u)
。
- 每次组成一个 “ku”,需要同时消耗一个
-
返回结果:
- 返回能够组成 “ku” 的最大数量。
3. 伪代码
以下是伪代码逻辑:
function solution(s):
初始化 countK = 0, countU = 0
遍历字符串 s 中的每个字符 c:
如果 c 是 'k' 或 'K',增加 countK
如果 c 是 'u' 或 'U',增加 countU
返回 min(countK, countU)
总结
解题的核心是统计两个目标字符的频率,并取其较小值作为结果。通过简单的遍历和条件判断即可实现。代码优化主要集中在可读性和效率提升方面,例如用 Character.toLowerCase
简化大小写处理,用 Math.min
替代手动判断等。
参考代码(Java)
public class Main {
public static int solution(String s) {
// 初始化 k 和 u 的计数器
int countK = 0, countU = 0;
// 遍历字符串并统计 k 和 u 的出现次数(忽略大小写)
for (char c : s.toCharArray()) {
if (Character.toLowerCase(c) == 'k') {
countK++;
} else if (Character.toLowerCase(c) == 'u') {
countU++;
}
}
// 返回 k 和 u 中较小的计数值,代表最多能组成的 "ku" 数量
return Math.min(countK, countU);
}
public static void main(String[] args) {
System.out.println(solution("AUBTMKAxfuu") == 1);
System.out.println(solution("KKuuUuUuKKKKkkkkKK") == 6);
System.out.println(solution("abcdefgh") == 0);
}
}
代码分析
参数
String s
: 输入字符串,只包含大小写英文字符。
返回值
int
: 能组成 “ku” 的最大数量。
实现过程
-
变量初始化:
int countK = 0, countU = 0;
- 定义两个计数器,分别记录字符
k
和u
的数量。
- 定义两个计数器,分别记录字符
-
遍历字符串:
for (char c : s.toCharArray()) {
- 使用增强型
for
循环,将字符串s
转换为字符数组,并逐个访问字符。
- 使用增强型
-
统计字符频率:
if (Character.toLowerCase(c) == 'k') { countK++; } else if (Character.toLowerCase(c) == 'u') { countU++; }
- 使用
Character.toLowerCase
将字符转换为小写,避免区分大小写。 - 如果字符是
k
或u
,分别增加对应计数器。
- 使用
-
计算结果:
return Math.min(countK, countU);
- 每个 “ku” 需要一个
k
和一个u
,因此能组成的 “ku” 数量是countK
和countU
中较小值。
- 每个 “ku” 需要一个
复杂度分析
-
时间复杂度:
- 遍历字符串一次,时间复杂度为 O(n) ,其中 n 是字符串长度。
-
空间复杂度:
- 使用了两个整型变量
countK
和countU
,空间复杂度为 O(1) 。
- 使用了两个整型变量