提问人:Ionnafan 提问时间:2/1/2023 最后编辑:Ionnafan 更新时间:2/2/2023 访问量:62
编写一个函数,用于确定每行连续 BA、CA 字符对的最大数量
Write a function that determines the maximum number of consecutive BA, CA character pairs per line
问:
尊敬的同事们。 我需要编写一个函数来确定每行连续 BA、CA 字符对的最大数量。
print(f("BABABA125")) # -> 3
print(f("234CA4BACA")) # -> 2
print(f("BABACABACA56")) # -> 5
print(f("1BABA24CA")) # -> 2
实际上,我已经编写了一个函数,但是,在我看来,它不是很好。
def f(s: str) -> int:
res = 0
if not s:
return res
cur = 0
i = len(s) - 1
while i >= 0:
if s[i] == "A" and (s[i-1] == "B" or s[i-1] == "C"):
cur += 1
i -= 2
else:
if cur > res:
res = cur
cur = 0
i -= 1
else:
if cur > res:
res = cur
return res
此外,我不允许使用库和正则表达式(仅字符串和列表方法)。您能否帮助我或在这种情况下对我的代码进行评分。我将不胜感激。
答:
1赞
Fractalism
2/1/2023
#1
下面是执行此操作的函数。f2
if not re.search('(BA|CA)', s): return 0
首先检查字符串是否实际包含任何 OR(以防止在步骤 3 中),如果没有,则返回 0。BA
CA
ValueError: max() arg is an empty sequence
matches = re.finditer(r'(?:CA|BA)+', s)
查找 或 的所有连续序列,使用非捕获组来确保输出仅完全匹配而不是部分匹配。CA
BA
re.finditer
res = max(matches, key=lambda m: len(m.group(0)))
然后,在匹配对象(对象)中,使用获取匹配的子字符串并比较它们的长度以找到最长的子字符串。re.Match
m.group(0)
return len(res.group(0))//2
将最长结果的长度除以 2 可得到此子字符串中的 or 个数。这里我们使用底线除法将输出强制为 ,因为除法通常会将答案转换为 。BA
CA
//
int
float
import re
strings = [
"BABABA125", # 3
"234CA4BACA", # 2
"BABACABACA56", # 5
"1BABA24CA", # 2
"NO_MATCH_TO_BE_FOUND", # 0
]
def f2(s: str):
if not re.search('(BA|CA)', s): return 0
matches = re.finditer(r'(?:CA|BA)+', s)
res = max(matches, key=lambda m: len(m.group(0)))
return len(res.group(0))//2
for s in strings:
print(f2(s))
更新:感谢 @StevenRumbalski 提供上述答案的更简单版本。(为了便于阅读,我将其分成多行)
def f3(s):
if not re.search('(BA|CA)', s): return 0
matches = re.findall(r'(?:CA|BA)+', s)
max_length = max(map(len, matches))
return max_length // 2
if not re.search('(BA|CA)', s): return 0
同上matches = re.findall(r'(?:CA|BA)+', s)
查找 或 的所有连续序列,但 中的每个值都是 a 而不是 ,这更容易处理。CA
BA
matches
str
re.Match
max_length = max(map(len, matches))
将每个匹配的子字符串映射到其长度,并找到其中的最大长度。return max_length // 2
Floor 将最长的匹配子字符串的长度除以 的长度,得到此字符串中 or 的连续出现次数。BA
CA
BA
CA
评论
1赞
Steven Rumbalski
2/1/2023
从 to 消除群体的尴尬re.finditer()
re.findall()
max(map(len, re.findall(r'(?:CA|BA)+', s)), default=0) // 2
1赞
Fractalism
2/1/2023
@StevenRumbalski 不错!我一开始打算使用,但当我看到奇怪的输出(第一次处理重叠组)时被难住了,所以我只选择了第一个工作解决方案。我稍后会将其添加到我的答案中,谢谢!findall
0赞
Ionnafan
2/2/2023
@Fractalism 我非常感谢你。但我真的没想到会这么难)))我不被允许使用库或正则表达式。
0赞
Fractalism
2/2/2023
#2
下面是一个没有任何导入的替代实现。但是请注意,与 C 样式实现相比,它非常慢。
这个想法很简单:将输入字符串转换为仅由两种类型的字符组成的字符串,并用 表示 或 ,并表示其他任何内容。然后找到连续 s 的最长子字符串。c1
c2
c1
CA
BA
c2
c1
具体实现如下:
- 选择一个保证不会出现在输入字符串中的字符;这里我们举个例子。然后选择一个与前一个不同的字符;这里我们使用 .
+
-
- 将 和 替换为 .
CA
BA
+
- 将字符串中的所有其他内容(不是 )替换为 (这就是为什么原始输入字符串中不能存在的原因)。现在我们有一个完全由 s 和 s 组成的字符串。
+
-
+
+
-
- 使用 as 分隔符拆分字符串,并将每个生成的子字符串映射到其长度。
-
- 返回这些子字符串长度的最大值。
strings = [
"BABABA125", # 3
"234CA4BACA", # 2
"BABACABACA56", # 5
"1BABA24CA", # 2
"NO_MATCH_TO_BE_FOUND", # 0
]
def f4(string: str):
string = string.replace("CA", "+")
string = string.replace("BA", "+")
string = "".join([(c if c == "+" else "-") for c in string])
str_list = string.split("-")
str_lengths = map(len, str_list)
return max(str_lengths)
for s in strings:
print(f4(s))
评论