📜  形成回文的最少插入| DP-28(1)

📅  最后修改于: 2023-12-03 14:54:15.151000             🧑  作者: Mango

形成回文的最少插入

本题目是经典的动态规划问题,题意为给定一个字符串,需要在其中插入最少的字符,使得该字符串成为回文字符串。具体的做法是,使用动态规划算法计算字符串中每个子串的最小插入次数,最终得到的结果即为原始字符串的最小插入次数。

问题分析

首先我们需要明确什么是回文字符串:即正着读和反着读都一样的字符串。比如 "racecar" 和 "level" 就是回文字符串。

假设给定的字符串为S,我们可以利用动态规划的思想,从字符串的两端开始扩展,判断两端的字符是否相同,如果相同,我们可以将两端的指针向中间移动,否则我们需要插入一个字符,此时我们可以在左端插入一个与右端相同的字符,或者在右端插入一个与左端相同的字符,以此来保证字符串的回文性质。

设 dp[i][j] 表示将 S[i:j+1] 变成回文字符串所需要的最少插入次数,那么我们可以得到状态转移方程:

  • 当 S[i] == S[j] 时,dp[i][j] = dp[i+1][j-1]
  • 当 S[i] != S[j] 时,dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1

其中,当 S[i] == S[j] 时,说明 S[i:j+1] 已经是回文字符串,那么我们只需要考虑将它的子串变成回文串即可,即 dp[i][j] = dp[i+1][j-1]。当 S[i] != S[j] 时,需要在该字符串的两端分别插入一个字符,使得 S[i:j+1] 变成回文串,那么我们只需要考虑在其中的一个端点插入字符即可,因此 dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1。

最后,dp[0][n-1] 就是将整个字符串变成回文字符串所需要的最小插入次数,其中 n 是字符串的长度。

代码实现
def min_insertions(s: str) -> int:
    n = len(s)
    dp = [[0] * n for _ in range(n)]

    for i in range(n-2, -1, -1):
        for j in range(i+1, n):
            if s[i] == s[j]:
                dp[i][j] = dp[i+1][j-1]
            else:
                dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1

    return dp[0][n-1]

以上是python的实现,时间复杂度为 $O(n^2)$,空间复杂度为 $O(n^2)$。