动态规划:让字符串成为回文串的最少插入次数

目录

题目

思路 

解题过程 

复杂度

code


题目

        给你一个字符串 s ,每一次操作你都可以在字符串的任意位置插入任意字符。请你返回让 s 成为回文串的 最少操作次数 。「回文串」是正读和反读都相同的字符串。

示例 1:

输入:s = "zzazz"
输出:0
解释:字符串 "zzazz" 已经是回文串了,所以不需要做任何插入操作。

示例 2:

输入:s = "mbadm"
输出:2
解释:字符串可变为 "mbdadbm" 或者 "mdbabdm" 。

示例 3:

输入:s = "leetcode"
输出:5
解释:插入 5 个字符后字符串变为 "leetcodocteel" 。

提示:

  • 1 <= s.length <= 500
  • s 中所有字符都是小写字母。

思路 

        这个问题可以通过动态规划来解决,具体是最长公共子序列(LCS)问题的一个变体。我们的目标是找到一个最少的插入次数,使得给定的字符串s成为回文串。


解题过程 

  1. 定义状态:设dp[i][j]表示字符串s从索引ij的子串最少需要插入的字符数,以使其成为回文串。

  2. 状态转移方程:如果s[i] == s[j],那么dp[i][j] = dp[i + 1][j - 1],因为两个相同的字符不需要插入就可以形成回文。如果s[i] != s[j],我们需要在ij之间插入字符,使得子串成为回文,此时dp[i][j] = 1 + min(dp[i + 1][j], dp[i][j - 1])

  3. 初始化:对于所有的idp[i][i] = 0,因为单个字符总是回文的。

  4. 计算顺序:我们可以从小到大计算dp[i][j],即先计算短的子串,然后使用这些结果来计算更长的子串。

  5. 构造最优解:最终,dp[0][n-1](其中n是字符串s的长度)将给出整个字符串s成为回文串的最少操作次数。


复杂度

  • 时间复杂度O(n^2),其中n是字符串s的长度。我们需要计算一个n x n的动态规划表。
  • 空间复杂度O(n^2),用于存储动态规划表。

code

def minInsertions(s):
    n = len(s)
    # 初始化动态规划表
    dp = [[0] * n for _ in range(n)]
    
    # 从最长为2的子串开始,逐步增加长度
    for length in range(2, n + 1):
        for i in range(n - length + 1):
            j = i + length - 1
            if s[i] == s[j]:
                dp[i][j] = dp[i + 1][j - 1]
            else:
                dp[i][j] = 1 + min(dp[i + 1][j], dp[i][j - 1])
    
    return dp[0][n - 1]

# 示例
print(minInsertions("zzazz"))  # 输出:0
print(minInsertions("mbadm"))  # 输出:2
print(minInsertions("leetcode"))  # 输出:5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值