题目描述
给定一个字符串 croakOfFrogs,它表示多个青蛙发出的叫声序列。每个青蛙必须按顺序发出 "c", "r", "o", "a", "k" 这五个字符。如果字符串有效,返回所需的最少青蛙数量;否则返回 -1。
解题思路
这道题的核心在于模拟青蛙叫声的状态流转。我们可以将 "c", "r", "o", "a", "k" 视为五个状态。
- 状态追踪:我们需要知道当前有多少只青蛙处于哪个阶段。例如,有多少只青蛙刚叫完 'c',准备叫 'r'。
- 复用机制:当一只青蛙完成 'k' 的叫声后,它可以立即开始新一轮的 "c"。这是减少总青蛙数量的关键。
- 合法性校验:如果在某个时刻需要进入下一个状态(如从 'c' 到 'r'),但没有处于上一状态的青蛙,说明序列无效,直接返回 -1。
具体实现上,可以使用一个长度为 5 的数组来记录各阶段的青蛙数量。遍历字符串时:
- 遇到 'c':优先复用已完成 'k' 的青蛙(如果有),否则新增一只青蛙。
- 遇到 'r', 'o', 'a', 'k':检查前驱状态是否有青蛙,有则转移计数,无则非法。
- 遍历结束:检查所有中间状态是否为 0,确保没有青蛙卡在半路。
代码实现
下面是具体的 C++ 实现,使用了数组模拟哈希表来优化性能。
class Solution {
public:
int minNumberOfFrogs(string croakOfFrogs) {
string s = "croak";
int n = s.size();
// 记录字符对应的状态索引
unordered_map<char, int> index;
for (int i = 0; i < n; ++i) {
index[s[i]] = i;
}
// hash[i] 表示处于第 i 个状态(s[i])的青蛙数量
vector<int> hash(n);
for (char ch : croakOfFrogs) {
if (ch == 'c') {
// 尝试复用刚完成 'k' 的青蛙
if (hash[n - 1] > 0) {
hash[n - 1]--;
}
hash[]++;
} {
t = index[ch];
(hash[t - ] == ) {
;
}
hash[t - ]--;
hash[t]++;
}
}
( i = ; i < n - ; ++i) {
(hash[i] != ) {
;
}
}
hash[n - ];
}
};


