📌  相关文章
📜  最小化要更改的字符以使字符串的左右旋转相同(1)

📅  最后修改于: 2023-12-03 15:40:16.194000             🧑  作者: Mango

最小化要更改的字符以使字符串的左右旋转相同

在字符串旋转问题中,常见的问题是判断两个字符串是否由旋转得到。但是有时候我们想知道,如果一个字符串不是旋转后得到的另一个字符串,我们需要更改多少个字符才能使其成为旋转字符串。

问题描述

给定一个字符串 s, 请你计算最少的字符修改数,使得 s 的左旋转和右旋转等价。

左旋转操作是指把字符串 s 最左边的字符移到最右边,例如 abc 左旋转一次得到 bca,将 bca 左旋转一次得到 cab,将 cab 左旋转一次又得到原始字符串 abc

示例

输入: s="aba" 输出: 1 解释: 本例中,将 s 右旋转一次得到 aab,只需要将其中的一个 a 替换成 b 即可。

输入: s="abcde" 输出: 2 解释: 本例中,将 s 右旋转一次得到 eabcd,只需要将其中的两个字符依次替换成 cd,即可得到左右旋转相等的字符串。

解法

我们可以考虑枚举旋转点,即在哪个位置将字符串分为左右两部分,并判断调整左右字符串各自所需的最小修改数。

回文串的判断可以使用双指针从两端向中间扫描的方式,但因为本题中有字符需要替换,所以需要稍微修改一下回文串的判断方法。我们可以使用双指针分别指向左右两部分的首字母,然后每次比较两个指针指向的字符是否相等,如果相等,将两个指针都往前移动一位,否则需要将其中一个指针指向的字符替换成另一个指针指向的字符,然后继续比较下一对字符。

代码实现

请参考以下 Python 代码实现:

def min_changes(s: str) -> int:
    n = len(s)
    ans = n
    for i in range(n):
        l, r = i - 1, i
        cnt = 0
        while l >= 0 and r < n:
            if s[l] == s[r]:
                l -= 1
                r += 1
            elif cnt < 1:
                cnt += 1
                l -= 1
                r += 1
            else:
                break
        if l < 0:
            ans = min(ans, n - r + i)
        l, r = i, i + 1
        cnt = 0
        while l >= 0 and r < n:
            if s[l] == s[r]:
                l -= 1
                r += 1
            elif cnt < 1:
                cnt += 1
                l -= 1
                r += 1
            else:
                break
        if l < 0:
            ans = min(ans, n - r + i + 1)
    return ans

其中,时间复杂度为 $O(n^2)$,空间复杂度为 $O(1)$。

总结

本题是字符串旋转问题的一个变体,需要我们计算最少修改字符数将一个字符串变为一个左右旋转相等的字符串。考虑枚举旋转点,然后分别计算左右两部分字符串所需的最小修改数。通过双指针的方法可以判断一个字符串是否为回文串或者左右旋转相等的字符串。