题目
标题和出处
标题:数青蛙
出处:1419. 数青蛙
难度
7 级
题目描述
要求
给你一个字符串 croakOfFrogs \texttt{croakOfFrogs} croakOfFrogs,它表示不同青蛙发出的蛙鸣声(字符串 "croak" \texttt{"croak"} "croak")的组合。由于同一时间可以有多只青蛙呱呱作响,所以 croakOfFrogs \texttt{croakOfFrogs} croakOfFrogs 中会混合多个 "croak" \texttt{"croak"} "croak"。请你返回模拟字符串中所有蛙鸣所需不同青蛙的最少数目。
注意:要想发出蛙鸣 "croak" \texttt{"croak"} "croak",青蛙必须依序输出 ‘c’, ‘r’, ‘o’, ‘a’, ‘k’ \texttt{`c', `r', `o', `a', `k'} ‘c’, ‘r’, ‘o’, ‘a’, ‘k’ 这 5 \texttt{5} 5 个字母。如果没有输出全部五个字母,那么它就不会发出声音。
如果字符串 croakOfFrogs \texttt{croakOfFrogs} croakOfFrogs 不是由若干有效的 "croak" \texttt{"croak"} "croak" 字符混合而成,请返回 -1 \texttt{-1} -1。
示例
示例 1:
输入:
croakOfFrogs
=
"croakcroak"
\texttt{croakOfFrogs = "croakcroak"}
croakOfFrogs = "croakcroak"
输出:
1
\texttt{1}
1
解释:一只青蛙“呱呱”两次。
示例 2:
输入:
croakOfFrogs
=
"crcoakroak"
\texttt{croakOfFrogs = "crcoakroak"}
croakOfFrogs = "crcoakroak"
输出:
2
\texttt{2}
2
解释:最少需要两只青蛙,“呱呱”声用下划线标注。
第一只青蛙
"
cr
‾
c
oak
‾
roak"
\texttt{"}\underline{\texttt{cr}}\texttt{c}\underline{\texttt{oak}}\texttt{roak"}
"crcoakroak"
第二只青蛙
"cr
c
‾
oak
roak
‾
"
\texttt{"cr}\underline{\texttt{c}}\texttt{oak}\underline{\texttt{roak}}\texttt{"}
"crcoakroak"
示例 3:
输入:
croakOfFrogs
=
"croakcrook"
\texttt{croakOfFrogs = "croakcrook"}
croakOfFrogs = "croakcrook"
输出:
-1
\texttt{-1}
-1
解释:给出的字符串不是
"croak"
\texttt{"croak"}
"croak" 的有效组合。
示例 4:
输入:
croakOfFrogs
=
"croakcroa"
\texttt{croakOfFrogs = "croakcroa"}
croakOfFrogs = "croakcroa"
输出:
-1
\texttt{-1}
-1
数据范围
- 1 ≤ croakOfFrogs.length ≤ 10 5 \texttt{1} \le \texttt{croakOfFrogs.length} \le \texttt{10}^\texttt{5} 1≤croakOfFrogs.length≤105
- 字符串中的字符只有 ‘c’ \texttt{`c'} ‘c’, ‘r’ \texttt{`r'} ‘r’, ‘o’ \texttt{`o'} ‘o’, ‘a’ \texttt{`a'} ‘a’ 或者 ‘k’ \texttt{`k'} ‘k’
解法
思路和算法
由于一次蛙鸣包含 5 5 5 个字母,如果 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 是有效的蛙鸣组合,其长度一定是 5 5 5 的倍数。如果 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 的长度不是 5 5 5 的倍数,则一定不是有效的蛙鸣组合,返回 − 1 -1 −1。
有效的蛙鸣组合中,每个蛙鸣包含的 5 5 5 个字母必须是有序的,可以通过对每个字母计数的方式判断是否为有效的蛙鸣组合和计算青蛙的数目。
如果 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 是有效的蛙鸣组合,则对于每个不是 ‘c’ \text{`c'} ‘c’ 的字母,蛙鸣中的上一个字母一定在 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 中已经出现。例如,当 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 中存在字母 ‘r’ \text{`r'} ‘r’ 时,一定在字母 ‘r’ \text{`r'} ‘r’ 之前有字母 ‘c’ \text{`c'} ‘c’。假设字母 ‘c’, ‘r’, ‘o’, ‘a’, ‘k’ \text{`c', `r', `o', `a', `k'} ‘c’, ‘r’, ‘o’, ‘a’, ‘k’ 对应的下标分别是 0 , 1 , 2 , 3 , 4 0, 1, 2, 3, 4 0,1,2,3,4,则当遍历到下标为 index \textit{index} index 的字母时,进行如下操作:
-
当 index < 4 \textit{index} < 4 index<4 时,将下标 index \textit{index} index 对应的计数加 1 1 1;
-
当 index > 0 \textit{index} > 0 index>0 时,将下标 index − 1 \textit{index} - 1 index−1 对应的计数减 1 1 1,如果在更新计数之后,下标 index − 1 \textit{index} - 1 index−1 对应的计数变成负数,则 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 不是有效的蛙鸣组合,返回 − 1 -1 −1;
-
遍历结束之后,对于有效的蛙鸣组合,每个下标对应的计数都应该是 0 0 0,如果存在下标对应的计数不是 0 0 0,则返回 − 1 -1 −1。
为了计算所需不同青蛙的最少数目,需要在遍历过程中维护青蛙的数目。每次遍历到字母 ‘c’ \text{`c'} ‘c’ 时将青蛙的数目加 1 1 1,表示开始一个新的蛙鸣,遍历到字母 ‘k’ \text{`k'} ‘k’ 时将青蛙的数目减 1 1 1,表示一个蛙鸣的结束。遍历过程中维护青蛙数目的最大值,表示同时出现的蛙鸣数目的最大值,该数目即为所需不同青蛙的最少数目,如果青蛙数目少于该数目,则无法生成给定的蛙鸣组合。
代码
class Solution {
public int minNumberOfFrogs(String croakOfFrogs) {
int length = croakOfFrogs.length();
if (length % 5 != 0) {
return -1;
}
int curSize = 0, maxSize = 0;
int[] counts = new int[4];
for (int i = 0; i < length; i++) {
char c = croakOfFrogs.charAt(i);
int index = getIndex(c);
if (index == 0) {
counts[index]++;
curSize++;
maxSize = Math.max(maxSize, curSize);
} else {
counts[index - 1]--;
if (counts[index - 1] < 0) {
return -1;
}
if (index < 4) {
counts[index]++;
} else {
curSize--;
}
}
}
for (int i = 0; i < 4; i++) {
if (counts[i] != 0) {
return -1;
}
}
return maxSize;
}
public int getIndex(char c) {
switch (c) {
case 'c':
return 0;
case 'r':
return 1;
case 'o':
return 2;
case 'a':
return 3;
case 'k':
return 4;
default:
return -1;
}
}
}
复杂度分析
-
时间复杂度: O ( n + ∣ Σ ∣ ) O(n + |\Sigma|) O(n+∣Σ∣),其中 n n n 是字符串 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 的长度, Σ \Sigma Σ 表示字符集,这道题中的字符集包含 ‘c’, ‘r’, ‘o’, ‘a’, ‘k’ \text{`c', `r', `o', `a', `k'} ‘c’, ‘r’, ‘o’, ‘a’, ‘k’, ∣ Σ ∣ = 5 |\Sigma|=5 ∣Σ∣=5。需要遍历字符串 croakOfFrogs \textit{croakOfFrogs} croakOfFrogs 一次,以及需要遍历每个字母的计数一次。
-
空间复杂度: O ( ∣ Σ ∣ ) O(|\Sigma|) O(∣Σ∣),其中 Σ \Sigma Σ 表示字符集,这道题中的字符集包含 ‘c’, ‘r’, ‘o’, ‘a’, ‘k’ \text{`c', `r', `o', `a', `k'} ‘c’, ‘r’, ‘o’, ‘a’, ‘k’, ∣ Σ ∣ = 5 |\Sigma|=5 ∣Σ∣=5。空间复杂度主要为对每个字符计数的空间。