构造有效字符串的最少插入数

标签: 贪心 字符串 动态规划

难度: Medium

给你一个字符串 word ,你可以向其中任何位置插入 "a"、"b" 或 "c" 任意次,返回使 word 有效 需要插入的最少字母数。

如果字符串可以由 "abc" 串联多次得到,则认为该字符串 有效

示例 1:

输入:word = "b"
输出:2
解释:在 "b" 之前插入 "a" ,在 "b" 之后插入 "c" 可以得到有效字符串 "abc" 。

示例 2:

输入:word = "aaa"
输出:6
解释:在每个 "a" 之后依次插入 "b" 和 "c" 可以得到有效字符串 "abcabcabc" 。

示例 3:

输入:word = "abc"
输出:0
解释:word 已经是有效字符串,不需要进行修改。 

提示:

  • 1 <= word.length <= 50
  • word 仅由字母 "a"、"b" 和 "c" 组成。

Submission

运行时间: 24 ms

内存: 16.5 MB

class Solution:
    def addMinimum(self, s: str) -> int:
        ans = ord(s[0]) - ord(s[-1]) + 2
        for x, y in pairwise(map(ord, s)):
            ans += (y - x + 2) % 3
        return ans

Explain

题解的核心思路是检查给定字符串并确定需要补充多少个字符来使其成为有效的 'abc' 序列。初始的时候,比较字符串的第一个字符和最后一个字符,以决定在字符串首尾可能需要添加的字符数量。然后,遍历字符串中相邻的字符,计算两个字符之间可能需要插入的字符数。这是通过将每个字符转换为其 ASCII 值,计算差值并根据差值来决定插入的字符数量。具体来说,采用模3运算来确定需要插入的字符数,因为 'abc' 三个字符在循环中可以形成闭环。

时间复杂度: O(n)

空间复杂度: O(n)

# 解决方案类
class Solution:
    def addMinimum(self, s: str) -> int:
        # 初始化答案,考虑字符串的首尾字符需要额外添加的字符数
        ans = ord(s[0]) - ord(s[-1]) + 2
        # 遍历字符串中的每对相邻字符
        for x, y in pairwise(map(ord, s)):
            # 计算当前字符与下一个字符之间的ASCII差值,确定需要插入的字符数
            ans += (y - x + 2) % 3
        return ans

Explore

在解法中,字符之间的ASCII差值反映了它们在'abc'序列中的相对位置。由于'abc'三个字符在ASCII表中相邻('a'=97, 'b'=98, 'c'=99),因此如果两个连续字符是有效的'abc'序列的一部分,它们的ASCII差值应该是1(例如'a'到'b','b'到'c')。如果差值不是1,那么就表示在这两个字符之间缺少了一部分'abc'序列。例如,如果差值是2,这意味着缺少了一个字符来形成完整的'abc'序列。通过计算差值,并根据'abc'循环的特性(使用模3运算),可以确定需要插入多少字符来补全序列。

这个公式用于计算在字符串的开头和结尾可能需要添加的字符数量,以确保整个字符串可以形成由'abc'重复组成的有效序列。逻辑是考虑字符串如何循环成为一个连续的'abc'序列。`ord(s[0]) - ord(s[-1])`计算的是首字符和尾字符在'abc'序列中的相对位置差。加2是为了调整这个差值,确保无论正差值还是负差值,计算出来的结果都能正确反映出为了形成闭环的'abc'序列需要添加的字符数。这个数值通过模3的运算(在后续计算中),使得整个字符串首尾相接时能够符合'abc'的循环序列。

在使用`(y - x + 2) % 3`这个表达式时,加2的目的是为了确保得到的结果总是正数,这有助于正确计算出需要插入多少个字符来维持'abc'序列的连续性。由于ASCII值的差`y - x`可能是负数(例如当考虑字符顺序从'c'到'a'时),直接进行模3运算可能会得到负的余数,这在逻辑上不符合我们计算需要插入的字符数量的需求。加2之后,确保了无论原始差是正是负,模3后的结果都是非负数,正确表示了从一个字符到另一个字符需要补充的'abc'序列的长度。