字符串题目:数青蛙

题目

标题和出处

标题:数青蛙

出处: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} 1croakOfFrogs.length105
  • 字符串中的字符只有 ‘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 index1 对应的计数减 1 1 1,如果在更新计数之后,下标 index − 1 \textit{index} - 1 index1 对应的计数变成负数,则 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。空间复杂度主要为对每个字符计数的空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的车尔尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值