力扣 1419. 数青蛙

49 篇文章 1 订阅
4 篇文章 0 订阅

力扣 1419. 数青蛙

1. 题目

在这里插入图片描述

2. 思路

  • 本题就是一道 字符串模拟题;
  1. 题目说到了, 会混杂着青蛙的叫声, 如果字符串 croakOfFrogs 不是由若干有效的 “croak” 字符混合而成,请返回 -1, 那就是说如果有多余的 'c', 'r', 'o'等等, 比如 "croakcroa"
  2. 题目说了, 同一时间内可以有多只青蛙呱呱作响, 但是求的是模拟蛙鸣需要的不同青蛙的最少数目;
    1. 在这里插入图片描述
    2. 见上图, 都是 3个 croak, 为什么左边最少需要青蛙的个数就是3只, 而右边需要青蛙的最少数量就可以是2只?
      1. 一只青蛙叫完一定是按照顺序, 依次去发出 c, r, o, a, k这5个字母的, 最终结尾一定是'k', 一旦出现这种 croakx(x指的是任意字符)字符k之后还有其他的字符, 一定是不完整的蛙声, 即 return -1;也就是说我们可以遍历叫声字串,能最终到了'k'(如果不按顺序的, 比如 crkoa, k 之前应该是 a, 这样是到不了k的)说明收集到完整的青蛙蛙鸣, 那么过程中怎么统计青蛙数量?【判定是最少的】记住,遇到'c'起始说明是需要青蛙叫的(可以是之前的青蛙, 或者一只新的青蛙);具体思路如下:
    3. 可以将青蛙叫分成5种:
      3.1 刚才发出了 c 的声音;
      3.2 刚才发出了 r 的声音;
      3.3 刚才发出了 o 的声音;
      3.4 刚才发出了 a 的声音;
      3.5 刚才发出了 k 的声音;
    4. 遍历croakOfFrogs, 例如当前遍历到 r,那么就看看有没有青蛙刚才发出了 c 的声音,如果有,那么才能让它接着发出 r 的声音;
      4.1 用一个哈希表(数组)cnt 来维护这 c r o a k这五种青蛙的个数【cnt['c'] = 3, 说明发出 'c' 的 青蛙有3只】, 然后可能的种类就这么几种情况:
      4.2 遍历到 字符 'c'时,看看有没有青蛙刚才发出了 字符'k'的声音,如果有,那么复用这只青蛙(认为他还可以接着发出 下一个 蛙鸣 croak),让它接着发出 字符 'c'的声音,即 cnt[‘k’]-- 和 cnt[‘c’]++;如果没有这种青蛙,那么直接新产生一只青蛙发出 c 的声音,即 cnt[‘c’]++;
      4.3 遍历到 'r'时,看看有没有青蛙刚才发出了 字符 'c'的声音,如果有,那么复用这只青蛙,(同一只青蛙)让它接着发出 r 的声音,即 cnt[‘c’]-- 和 cnt[‘r’]++;如果没有这种青蛙,由于题目要求青蛙必须从 c 开始蛙鸣,不能直接从 r 开始【即 cnt[‘c’] == 0, 不能直接r开始】,所以返回 −1;
      4.4 遍历到 o,a,k的情况类似 r, 我们要做的就是找到这个字母的上一个字母对应映射cnt[‘x’] 有没有 > 0, 有就 -1, 说明可以复用, 并且当前的字母的cnt值+1, 但是 如果上一个字母的 cnt 值等于 0,那么就返回 −1
    5. 遍历结束后,所有青蛙必须在最后发出 k 的声音,如果有青蛙在最后发出的声音不是 k(也就是 cnt 值大于 0),那么返回 −1,否则返回 cnt[k];

3. 代码

class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) {
        const int N = 256;
        // 预处理,croak 每个字母的前一个值是什么
        vector<char> vctPre(N);    // 不然也可以用 map
        const string croak = "croakc";
        // c pre is k
        // r pre is c
        // 
        for (int i = 1; i < 6; ++i){

            // vctPre 存放的是(下标即当前 字符) 当前字符对应的 前一个字符是啥, 比如 'r' -> 'c')
            // 不然就得一个一个写 if else
            // croak[i - 1] = 'c'
            // ASCII码 vctPre['r'] = 'c' 即 r 的 前一个字符是 c
            vctPre[croak[i]] = croak[i - 1];
        }

        // 遍历一遍string 叫声字串
        vector<int> res(N, 0); // 统计结果的 res
        for(const auto& frog : croakOfFrogs){
            auto pre = vctPre[frog];    // 要知道当前字符的前一个字符是什么?
            if (res[pre]){
                // 按照顺序下来, 前一个字符有值, 可以复用这只青蛙
                res[pre]--;
            }else if (frog != 'c'){
                // 不然的话, 青蛙一定得从 c 开始蛙鸣
                return -1;
            }
            res[frog]++;
        }
        if (res['c'] || res['r'] || res['o'] || res['a']){
            return -1;  // 有发出其他的声音的青蛙
        }
        return res['k'];    // 最后所有的青蛙都发出'k'

    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

郑师傅炒板栗

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

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

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

打赏作者

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

抵扣说明:

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

余额充值