力扣算法--数青蛙与外观数列问题

引言
 
在力扣(LeetCode)的算法练习中,“数青蛙”和“外观数列”是两道很有意思的中等难度题目,它们分别从字符串的逻辑校验与计数、递归与字符串压缩的角度,考察我们对算法的理解和运用。本文将带大家深入剖析这两道题的解题思路与实现方法。
 
一、数青蛙(LeetCode 1419)
 
题目剖析
 
我们需要处理一个表示青蛙蛙鸣的字符串,判断其是否由有效“croak”组合而成,若有效,返回模拟这些蛙鸣所需不同青蛙的最少数目;若无效,返回 -1 。青蛙发出“croak”需依次输出 'c'、'r'、'o'、'a'、'k' 这 5 个字符,且要保证字符顺序和完整性。
 
解题思路
 
1. 初始化辅助结构:定义目标蛙鸣字符串 "croak",创建哈希数组  hash  记录每个阶段(对应 "croak" 每个字符位置)的青蛙数量,用  unordered_map  存储每个字符在目标字符串中的下标,方便快速查找。
2. 遍历处理输入字符串:
- 遇到 'c' 时,先查看是否有完成一轮“croak”(处于 'k' 阶段,即  hash  最后一个元素)的青蛙,若有则复用(该阶段数量减 1 ),然后增加 'c' 阶段数量;
- 遇到其他字符时,检查前一阶段数量是否为 0 ,为 0 说明字符顺序混乱,返回 -1 ,否则前一阶段数量减 1 ,当前阶段数量加 1 。

3. 结果验证与返回:遍历  hash  数组(除最后一个元素),若有非 0 值,说明蛙鸣不完整,返回 -1 ;否则返回最后一个元素值,即所需最少青蛙数。

 
代码实现
 

class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) {
        string tmp = "croak";
        int n = tmp.size();
        vector<int> hash(n, 0);
        
        unordered_map<char, int> index;
        for (int i = 0; i < n; ++i) {
            index[tmp[i]] = i;
        }
        
        int maxFrogs = 0;
        for (char e : croakOfFrogs) {
            int idx = index[e];
            if (e == 'c') {
                if (hash[n - 1] > 0) {
                    hash[n - 1]--;
                }
                hash[idx]++;
                maxFrogs = max(maxFrogs, hash[0]);
            } else {
                int prevIdx = idx - 1;
                if (hash[prevIdx] == 0) {
                    return -1;
                }
                hash[prevIdx]--;
                hash[idx]++;
            }
        }
        
        for (int i = 0; i < n - 1; ++i) {
            if (hash[i] != 0) {
                return -1;
            }
        }
        return maxFrogs;
    }
};

二、外观数列(LeetCode 38)
 
题目剖析
 
外观数列由递归公式定义, countAndSay(1) = "1" , countAndSay(n)  是  countAndSay(n - 1)  的行程长度编码(RLE),需要根据给定整数  n ,返回外观数列的第  n  个元素。行程长度编码是把连续相同字符替换为重复次数和该字符的串联。
 
解题思路
 
1. 初始化:从第 1 项  "1"  开始。
2. 迭代推导:循环  n-1  次,每次对当前字符串做「计数 + 描述」:
- 用双指针  left / right  找连续相同字符的区间。
- 拼接区间长度和字符,生成新字符串。
3. 返回结果:迭代完成后,得到第  n  项的外观数列。

 
本质是用迭代模拟行程长度编码(RLE),逐步推导结果,逻辑清晰高效 。
 
代码实现
 

class Solution {
public:
    string countAndSay(int n) {
        string ret="1";
        for(int i=1;i<n;i++)
        {
            string tmp;
            for(int left=0,right=0;right<ret.size();)
            {
                while(right<ret.size()&&ret[right]==ret[left])right++;
                tmp+=to_string(right-left)+ret[left];
                left=right;
            }
            ret=tmp;
        }
        return ret;
    }
};
 

三、总结
 
“数青蛙”题主要围绕字符串字符的顺序校验与计数逻辑,考察对复杂条件下字符串处理的能力;“外观数列”题则结合递归与行程长度编码,让我们体会到递归思想在字符串处理中的应用。通过练习这类题目,能有效提升我们分析问题、运用算法解决实际场景的能力,大家可以多在力扣上尝试不同解法,加深对算法的理解。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值