文章目录
- 前言
- 详解试题
- 1419. 数青蛙
- 华为机试题. 数大雁
- 题目解析
- 数青蛙代码实现
- 数大雁不考虑叫声不完整的情况
- 数大雁考虑叫声不完整的情况
前言
《华为机试真题详解》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。
如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议!
本文解法非最优解(即非性能最优)。
详解试题
平台 | 试题 |
LeetCode | 1419. 数青蛙(中等) |
华为机试 | 【华为机试真题 Python实现】数大雁【2022 Q2 100分】 |
1419. 数青蛙
给你一个字符串 croakOfFrogs,它表示不同青蛙发出的蛙鸣声(字符串 “croak” )的组合。由于同一时间可以有多只青蛙呱呱作响,所以 croakOfFrogs 中会混合多个 “croak” 。
请你返回模拟字符串中所有蛙鸣所需不同青蛙的最少数目。
要想发出蛙鸣 “croak”,青蛙必须 依序 输出 ‘c’, ’r’, ’o’, ’a’, ’k’ 这 5 个字母。如果没有输出全部五个字母,那么它就不会发出声音。如果字符串 croakOfFrogs 不是由若干有效的 “croak” 字符混合而成,请返回 -1 。
华为机试题. 数大雁
一群大雁往南飞,给定一个字符串记录地面上的游客听到的大雁叫声,请给出叫声最少由几只大雁发出。
具体的:
大雁发出的完整叫声为”quack“,因为有多只大雁同一时间嘎嘎作响,所以字符串中可能会混合多个”quack”。
大雁会依次完整发出”quack”,即字符串中’q’ ,‘u’, ‘a’, ‘c’, ‘k’ 这5个字母按顺序完整存在才能计数为一只大雁。如果不完整或者没有按顺序则不予计数。
如果字符串不是由’q’, ‘u’, ‘a’, ‘c’, ‘k’ 字符组合而成,或者没有找到一只大雁,请返回-1。
题目解析
我在LeetCode上有一道类似的题目,主要是对异常部分的描述有些不同,大家可以看下上面标黄的两句话。
在LeetCode测试发现只要字符串中的字符不能构成完整的叫声时,是不会计算有效字符串的个数的,直接输出-1
就可了。
数大雁这道题里多了一句或者没有找到一只大雁 就很奇怪了,就是有一个正常的就需要统计呗,这个明显增加的题目的难度,已经不是一道100分
的题目了,因为没有在正式的机试环境下测试过,大家可以按数青蛙
的解法先提交一次,如果不能完全通过再考虑复杂的情况。
下面我们就分别看下题目求解的思考过程,先以数青蛙为例:
我们用一个数组 states 来记录🐸叫个匹配状态
如果我们只是对字符计数的话,当遇到 kaorc
的情况就很难处理了,因为我们已知字符是顺序出现的,只有前一项的个数存在时后一项的字符才是有意义的,所有状态这里特殊处理一下,对后一项 +1 时 同时 对前一项 -1,这样当我们遇到字符 k 时 记录表中的数量和就是重复的🐸个数。
一只青蛙的计数:
有叫声重叠的计数:
计数是我们 假定 当前重叠的字符再未遍历的地方都有字符与之生成完整的叫声。
数青蛙代码实现
class Solution:
def minNumberOfFrogs(self, croakOfFrogs: str) -> int:
base = "croak"
states = [0] * len(base)
counts = 0
for c in croakOfFrogs:
if c == base[0]:
states[0] += 1
else:
index = base.index(c)
states[index-1] -= 1
states[index] += 1
if c == base[-1]:
states[-1] -= 1
# 如果再等于k时进行统计,需要在循环结束后再进行一次统计操作
# 最后一个字符时k的情况
counts = max(counts, sum(states))
# 出现-1时,说明无法构成croak,直接跳出
if -1 in states:
return -1
else:
if sum(states) != 0:
return -1
return
数大雁不考虑叫声不完整的情况
数大雁这道题,如果不考虑叫声不完整的情况只需要更换base = "quack"就可以了
while 1:
try:
chars = input()
base = "quack"
states = [0] * len(base)
counts = 0
for c in chars:
if c == base[0]:
states[0] += 1
else:
index = base.index(c)
states[index-1] -= 1
states[index] += 1
if c == base[-1]:
states[-1] -= 1
counts = max(counts, sum(states))
if -1 in states:
print(-1)
break
else:
if sum(states) != 0:
print(-1)
else:
print(counts)
数大雁考虑叫声不完整的情况
我们还用上面的图解释下这个情况,因为我们再前面的编码中假设后面的字符会存在,并且在遍历到后面时,发现不存在完整的字符会直接跳出循环,打印-1。
我在统计第一部分时就可以直接计算 sum(states)
为🐸的个数,但在数大雁的题目中复杂考虑的场景是不能使用这个假设的。
我们需要在统计时,减掉不完整的字符串导致的 多算的大雁个数,也就时在统计到k字符时,最多再向后遍历 sum(states)
-1 个k 来检查是否能构成完整的叫啥,不能构成的话需要减去对应的数量。
计算剩余字符串是否满足剩余的叫声
# 计算剩余字符串是否满足剩余的叫声
temp = [t for t in states]
temp[-1] = 0
max_ = sum(temp)
for j in range(i, len(chars)):
index = base.index(chars[j])
if temp[index - 1]:
temp[index - 1] -= 1
temp[index] += 1
if temp[-1] == max_:
break
数大雁完成代码实现
while 1:
try:
chars = input()
base = "quack"
states = [0] * len(base)
dp = []
for i in range(len(chars)):
index = base.index(chars[i])
if index == 0:
states[index] += 1
else:
if states[index - 1]:
states[index - 1] -= 1
states[index] += 1
if base[-1] == chars[i]:
if states[-1] != 0:
# 计算剩余字符串是否满足剩余的叫声
temp = [t for t in states]
temp[-1] = 0
max_ = sum(temp)
for j in range(i, len(chars)):
index = base.index(chars[j])
if temp[index - 1]:
temp[index - 1] -= 1
temp[index] += 1
if temp[-1] == max_:
break
dp.append(temp[-1] + 1)
states[-1] -= 1
print(max(dp) if dp else -1)
except Exception as e:
break