📜  构建字典序上最小的回文(1)

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

构建字典序上最小的回文

回文是指正着读和反着读都一样的字符串。给定一个字符串S,构建一个字典序上最小的回文。

方法

一种简单的方法是,从字符串的左右两端分别向中间遍历,并将不同的字符交换,以使得字符串变成回文。具体步骤如下:

  1. 初始化左右指针leftright,分别指向字符串的左右两端;
  2. 如果当前左右指针指向的字符相同,移动左指针向右,右指针向左;
  3. 如果不相同,就从右指针开始向左遍历,找到第一个和左指针指向的字符相同的字符,将其和左指针指向的字符交换,并将左指针向右移动一位;
  4. 针对上述步骤,如果在右指针向左遍历过程中没有找到与左指针指向的字符相同的字符,则说明左指针指向的字符在字符串的右半部分中没有出现过,此时只能从左指针开始向右遍历找到第一个和右指针指向的字符相同的字符,并进行交换,将右指针向左移动一位。

上述方法可以通过一个while循环进行实现,具体的代码如下所示。

def get_min_palindrome(s):
    left = 0
    right = len(s) - 1
    s_list = list(s)
    while left < right:
        if s_list[left] == s_list[right]:
            left += 1
            right -= 1
        else:
            found = False
            for i in range(right - 1, left - 1, -1):
                if s_list[i] == s_list[left]:
                    s_list[i], s_list[right] = s_list[right], s_list[i]
                    found = True
                    break
            if not found:
                for i in range(left + 1, right):
                    if s_list[i] == s_list[right]:
                        s_list[i], s_list[left] = s_list[left], s_list[i]
                        break
            left += 1
            right -= 1
    return ''.join(s_list)
测试

我们可以使用一些测试用例对上述方法进行验证,具体代码如下所示。

tests = [
    ('abcd', 'abcba'),
    ('aabb', 'abba'),
    ('race', 'racecar'),
    ('ab', 'aba'),
]

for s, expected in tests:
    result = get_min_palindrome(s)
    assert result == expected, f"Error: s={s}, expected={expected}, result={result}"
结语

到这里,我们就学习了如何构建字典序上最小的回文,而方法的核心思想是交换两个不同字符的位置。通过构造一些测试用例,我们也成功地验证了上述方法的正确性。最后需要注意的是,上述方法并不是唯一的构造字典序最小回文的方法,读者可以自行尝试其他方法。