编写一个函数,用于确定每行连续 BA、CA 字符对的最大数量

Write a function that determines the maximum number of consecutive BA, CA character pairs per line

提问人:Ionnafan 提问时间:2/1/2023 最后编辑:Ionnafan 更新时间:2/2/2023 访问量:62

问:

尊敬的同事们。 我需要编写一个函数来确定每行连续 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

此外,我不允许使用库和正则表达式(仅字符串和列表方法)。您能否帮助我或在这种情况下对我的代码进行评分。我将不胜感激。

Python 字符串 方法

评论

0赞 EJoshuaS - Stand with Ukraine 2/2/2023
请看:为什么“有人可以帮助我吗?”不是一个实际的问题?

答:

1赞 Fractalism 2/1/2023 #1

下面是执行此操作的函数。f2

  1. if not re.search('(BA|CA)', s): return 0
    首先检查字符串是否实际包含任何 OR(以防止在步骤 3 中),如果没有,则返回 0。BACAValueError: max() arg is an empty sequence
  2. matches = re.finditer(r'(?:CA|BA)+', s)
    查找 或 的所有连续序列,使用非捕获组来确保输出仅完全匹配而不是部分匹配。CABAre.finditer
  3. res = max(matches, key=lambda m: len(m.group(0)))
    然后,在匹配对象(对象)中,使用获取匹配的子字符串并比较它们的长度以找到最长的子字符串。re.Matchm.group(0)
  4. return len(res.group(0))//2
    将最长结果的长度除以 2 可得到此子字符串中的 or 个数。这里我们使用底线除法将输出强制为 ,因为除法通常会将答案转换为 。BACA//intfloat
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
  1. if not re.search('(BA|CA)', s): return 0
    同上
  2. matches = re.findall(r'(?:CA|BA)+', s)
    查找 或 的所有连续序列,但 中的每个值都是 a 而不是 ,这更容易处理。CABAmatchesstrre.Match
  3. max_length = max(map(len, matches))
    将每个匹配的子字符串映射到其长度,并找到其中的最大长度。
  4. return max_length // 2
    Floor 将最长的匹配子字符串的长度除以 的长度,得到此字符串中 or 的连续出现次数。BACABACA

评论

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 的最长子字符串。c1c2c1CABAc2c1

具体实现如下:

  1. 选择一个保证不会出现在输入字符串中的字符;这里我们举个例子。然后选择一个与前一个不同的字符;这里我们使用 .+-
  2. 将 和 替换为 .CABA+
  3. 将字符串中的所有其他内容(不是 )替换为 (这就是为什么原始输入字符串中不能存在的原因)。现在我们有一个完全由 s 和 s 组成的字符串。+-++-
  4. 使用 as 分隔符拆分字符串,并将每个生成的子字符串映射到其长度。-
  5. 返回这些子字符串长度的最大值。
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))