题目解析
- 一声有效的“蛙鸣”,必须依次输出字符
c r o a k
,例如corak
所组成的字符串不会发出声音- 一只青蛙无论怎么鸣叫,其结果必定是字符串
croak
的重复 - 鸣叫
n
声,则重复n
次croak
- 一只青蛙无论怎么鸣叫,其结果必定是字符串
- 两只青蛙一齐鸣叫一次的结果是字符
c r o a k
的组合,即有如下可能croakcroak
croakcroak
可以代表两只青蛙一齐鸣叫的一种结果,也可以代表一只青蛙连续鸣叫两次- 所以,才有所求——所需青蛙的最少数目
crcoakroak
- 如下图
思路分析
- 代表蛙鸣的字符串组成有且仅有
'c' 'r' 'o' 'a' 'k'
- 能发出声音的组合必须是
c->r->o->a->k
- 有效哇鸣,字符
c
必须前面,字符k
必须在最后面
- 有效哇鸣,字符
- 遍历给定的代表哇鸣的字符串
croakOfFrogs
- 用五个变量分别对字符
'c' 'r' 'o' 'a' 'k'
进行计数 - 假设一组哇鸣中,最少需要
n
个青蛙一起鸣叫组成- 那么肯定有
n
个字符c
先于n
个字符r
出现 - 字符
r
先于字符o
出现 - 字符
o
先于字符a
出现 - 字符
a
先于字符k
出现
- 那么肯定有
- 在遍历过程中记录各个字符出现的次数,最终每一个字符出现的字符次数相同
- 并且在遍历过程中按照顺序
c->r->o->a->k
依次出现的次数 - 能够发出声音的情况下,各个字符出现的次数必须满足 C n t c > C n t r > C n t o > C n t a > C n t k Cnt_c>Cnt_r>Cnt_o>Cnt_a>Cnt_k Cntc>Cntr>Cnto>Cnta>Cntk
- 否则直接返回-1
- 由于最终所要求最少需要多少个青蛙一齐哇鸣,所以各个字符出现的次数即为需要的最少青蛙数
- 并且在遍历过程中按照顺序
- 用五个变量分别对字符
- 如何求得所需要的最少青蛙数?
- 思路倒着来
ex: croak; ans = 0
- 出现字符
c
,进行计数 C n t c = 1 Cnt_c = 1 Cntc=1,所需要青蛙数ans++
- 出现字符
r
,进行计数 C n t r = 1 Cnt_r = 1 Cntr=1并对 C n t c Cnt_c Cntc做减一操作,此时 C n t c = 0 Cnt_c=0 Cntc=0 - 依次类推
- 出现字符
k
,之后有 C n t k = 1 , C n t c , r , o , a = 0 , a n s = 1 Cnt_k = 1,Cnt_{c,r,o,a}=0,ans=1 Cntk=1,Cntc,r,o,a=0,ans=1- 遍历完毕仅有 C n t k ! = 0 Cnt_k!=0 Cntk!=0
- 一次遍历完毕,判断是否满足 C n t c , r , o , a = 0 Cnt_{c,r,o,a}=0 Cntc,r,o,a=0,不满足直接跳出循环,返回-1
- 出现字符
- 由于可能出现此种情况
ex: croakccrrooaakk
,很明显需要最少2个青蛙一齐鸣叫- 当遍历到第二个字符
c
的时候, C n t k ! = 0 Cnt_k!=0 Cntk!=0 - 所以出现字符
c
的时候需要判断k > 0,k--
- 否则
ans++
- 当遍历到第二个字符
- 思路倒着来
code
public int minNumberOfFrogs(String croakOfFrogs) {
int n = croakOfFrogs.length();
// 必须是5的倍数
if(n % 5 != 0) {
return -1;
}
// 计数变量
int c,r,o,a,k;
c = r = o = a = k = 0;
// 所需青蛙数
int ans = 0;
for(int i = 0;i < n;i++) {
char at = croakOfFrogs.charAt(i);
if(at == 'c') {
c++;
if(k > 0) {
k--;
} else {
ans++;
}
} else if(at == 'r') {
r++;
c--;
} else if(at == 'o') {
o++;
r--;
} else if(at == 'a') {
a++;
o--;
} else if(at == 'k') {
k++;
a--;
}
//出现 小于 0的情况,字符串无效
if(c < 0 || r < 0 || o < 0 || a < 0) {
return -1;
}
}
// 遍历完成需要满足 c = r = o = a = 0;
if(c != 0 || r != 0 || o != 0 || a != 0) {
return -1;
}
return ans;
}
心得体会
- 巧妙利用了字符顺序出现的性质,利用计数的方法解决
- 计数过程中的加减转化颇为巧妙
- 要灵活运用题目中所给出的已知条件
- 不要钻牛角尖
- 再次遇到字符串相关题目要有以下思路
- 是否可以计数解决
- KMP解决(从一个字符串中寻找另外一个字符串出现的次数)
- manacher算法(回文串)
- 二分查找
- 多多尝试
参考
https://leetcode.cn/problems/minimum-number-of-frogs-croaking/
https://leetcode.cn/problems/minimum-number-of-frogs-croaking/solution/cai-ji-gong-xian-ge-chun-onzuo-fa-by-imcover/