文章目录
- 【模拟】2023B-数大雁
- 题目描述与示例
-
- 题目描述
- 输入
- 输出
- 示例一
-
- 输入
- 输出
- 示例二
-
- 输入
- 输出
- 示例三
-
- 输入
- 输出
- 说明
- 示例四
-
- 输入
- 输出
- 说明
- 解题思路
- 代码
-
- 时空复杂度
- 华为OD算法冲刺训练
【模拟】2023B-数大雁
题目描述与示例
题目描述
一群大雁往南飞,给定一个字符串记录地面上的游客听到的大雁叫声,请给出叫声最少由几只大雁发出。
具体的:
- 大雁发出的完整叫声为
"quack"
,因为有多只大雁同一时间嘎嘎作响,所以字符串中可能会混合多个"quack"
。 - 大雁会依次完整发出
"quack"
,即字符串中"q" ,"u", "a", "c", "k"
这 5 个字母按顺序完整存在才能计数为一只大雁。如果不完整或者没有按顺序则不予计数。 - 如果字符串不是由
"q" ,"u", "a", "c", "k"
字符组合而成,或者没有找到一只大雁,请返回-1
。
输入
一个字符串,包含大雁 quack
的叫声。1 <= 字符串长度 <= 1000
,字符串中的字符只有 "q" ,"u", "a", "c", "k"
。
输出
大雁的数量
示例一
输入
Python
quackquack
输出
Python
1
示例二
输入
Python
qaauucqcaa
输出
Python
-1
示例三
输入
Python
quacqkuackquack
输出
Python
2
说明
用不同的颜色表示同一只大雁,quac``q``k``uack``quack
,最少需要2
只大雁。
以下情况都是2
只大雁。
quac``q``k``uack``quack
quac``q``k``uac``q``k``uack
quac``q``k``ua``q``ck``uack
quac``q``k``u``q``ack``uack
quac``q``kq``uack``uack
以下情况需要3
只大雁。
quac``q``q``k``uack``uack
qua``q``c``q``k``uack``uack
示例四
输入
Python
quacqkuquacqkacuqkackuack
输出
Python
3
说明
用不同的颜色表示同一只大雁,quacqkuquacqkacuqkackuack,最少需要3
只大雁。
解题思路
注意,本题和LC1419. 数青蛙完全一致。
说实话这题乍一看很让人一头雾水。但其实就是根据题意直接模拟即可,主要问题在于大雁能否可以复用这个问题比较麻烦。
首先考虑返回-1
,即无法完成所有雁叫的情况:
- 原字符串
s
中,所有字符出现的数目不一致,这个可以在最开始的时候做特殊情况的判断。 - 遍历到某个字符
ch
时,比如'c'
,发现其前一个字符即'a'
出现的次数少于当前字符,那么无法实现一个完整的雁叫。
我们考虑用一个长度为5
的cnt
数组,来记录"quack"
中每个字符被叫了几次,即每个字符的出现个数。要注意,cnt
中的计数,并不代表大雁的总个数。cnt
的更新直接在循环中进行即可。
再考虑大雁是否可以复用的问题。假设遇到一个新的'q'
,表示出现了一声新的"quack"
,如果此时:
'k'
的计数大于0
,表示之前有某只大雁叫完了,那么这只大雁可以立马抓来复用,我们对cnt
整体减1
。'k'
的计数等于0
,表示之前没有任何大雁完成了雁叫,或是先前完成了雁叫的大雁被抓去复用了(无需分辨这两种情况的区别),因此再无需进行任何操作。
思路基本就结束了。这里可以使用一个哈希表word
用于取"quack"
的各个字符分别对应的01234
在cnt
中的索引idx
,即存在word = {ch: i for i, ch in enumerate("quack")}
,idx
在计数过程和判断无法完成雁叫两个地方都会用到。
代码
python
# 题目:2023B-数大雁
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:模拟
# 代码看不懂的地方,请直接在群上提问
s = input()
# 构建一个标记,表示是否出现了异常,初始化为False表示没有异常
isError = False
# 排除特殊情况,如果各个字符总数不一致,出现异常
if len(set(collections.Counter(s).values())) != 1:
# 标记isError改为True
isError = True
else:
# 构建哈希表,"quack"分别对应01234一共五个索引
word = {ch: i for i, ch in enumerate("quack")}
# cnt列表:记录"quack"中每个字符被叫了几次,即每个字符的出现个数。
# 要注意,cnt中的计数,并不代表大雁的总个数。
cnt = [0, 0, 0, 0, 0]
for ch in s:
# 获得字符ch在列表cnt中的索引idx,即表示"quack"对应的01234一共五个索引
idx = word[ch]
# ch对应的计数+1
cnt[idx] += 1
# ch不是"q",且前一个字符数目少于当前字符数目,出现错误
if ch != "q" and cnt[idx] > cnt[idx-1]:
# 标记isError改为True,同时退出循环
isError = True
break
# 遇到"q",表示出现新的雁叫,可能可以复用之前的大雁,如果:
# 1. 之前有某大雁叫过"k",那么这只大雁可以复用,cnt整体-1,表示可以少算一只大雁
# 2. 之前没有大雁叫过"k",那么无法进行大雁的复用,无需做任何操作
# cnt[4]表示之前叫过"k"的大雁的个数,
# cnt[4] >= 1即表示,存在某大雁叫过"k",这只大雁可以拿来复用
if ch == "q" and cnt[4] >= 1:
cnt = [item-1 for item in cnt]
# 如果isError为True,说明出现了异常,输出-1
# 否则最终cnt中所有计数一致,这个数即为所需要的大雁的个数,输出之
print(-1) if isError else print(cnt[0])
时空复杂度
时间复杂度:O(N)
。仅需一次遍历数组。
空间复杂度:O(1)
。仅需若干常数变量。
华为OD算法冲刺训练
-
华为OD算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
-
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
-
30+天陪伴式学习,20+直播课时,300+动画图解视频,200+LeetCode经典题,100+华为OD真题,还有简历修改与模拟面试将为你解锁
-
可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)
-
绿色聊天软件戳
od1336
了解更多