📌  相关文章
📜  生成字符串回文的最少删除次数 | 2套(1)

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

生成字符串回文的最少删除次数

在字符串处理中,常常会遇到需要将一个字符串变成回文的问题。回文是指正着读和反着读都一样的字符串。在将一个字符串变成回文的过程中,我们可以进行删除和插入等操作来改变这个字符串。本文将介绍两种不同的算法,分别是贪心算法和动态规划算法,来解决生成字符串回文的最少删除次数问题。

贪心算法

贪心算法的基本思想是,在每个步骤中选择最优的解决方案,最终得到全局最优解。在本问题中,我们可以使用贪心算法来找到最少的删除次数,具体步骤如下:

  1. 定义两个指针,分别指向字符串的头和尾。
  2. 只要头指针所指的字符与尾指针所指的字符不相等,那么就需要将其中一个字符删除,最终的删除次数即为不相等的字符的个数。
  3. 如果头指针和尾指针所指字符相等,则将头指针和尾指针向中间移动,重复第二步直到头指针和尾指针相遇。

贪心算法的时间复杂度为 $O(n)$,其中 $n$ 是字符串的长度,空间复杂度为 $O(1)$。以下是贪心算法的Python代码实现:

def min_deletions(s: str) -> int:
    left, right = 0, len(s) - 1
    deletions = 0
    while left < right:
        if s[left] != s[right]:
            deletions += 1
            if s[left + 1] == s[right]:
                left += 1
            elif s[left] == s[right - 1]:
                right -= 1
            else:
                left += 1
                right -= 1
        else:
            left += 1
            right -= 1
    return deletions
动态规划算法

动态规划算法的基本思想是将问题分解成子问题进行求解,并将子问题的解缓存起来,避免重复求解。在本问题中,我们可以使用动态规划算法来找到最少的删除次数,具体步骤如下:

  1. 定义状态:$dp[i][j]$ 表示将字符串 $s_i$ 到 $s_j$ 变成回文的最少删除次数。
  2. 状态转移方程:

如果 $s_i == s_j$,可以直接将目前的字符视作回文,因此 $dp[i][j] = dp[i + 1][j - 1]$。

如果 $s_i \neq s_j$,则需要考虑删除其中一个字符,使得 $s_i$ 到 $s_j$ 变成回文。我们可以通过删除 $s_i$ 或者 $s_j$ 中的一个字符来实现,这样问题就转化为了 $s_{i + 1}$ 到 $s_j$ 或者 $s_i$ 到 $s_{j - 1}$ 成为回文需要的最少删除次数再加上一次删除即可。因此,$dp[i][j] = \min(dp[i + 1][j], dp[i][j - 1]) + 1$。

  1. 边界条件:当 $i == j$ 时,$dp[i][j] = 0$。

动态规划算法的时间复杂度为 $O(n^2)$,其中 $n$ 是字符串的长度,空间复杂度为 $O(n^2)$。以下是动态规划算法的Python代码实现:

def min_deletions(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]

两种算法的核心思想不同,贪心算法是每次删除当前局部最优的字符,而动态规划算法是将问题分解成子问题,通过子问题的解缓存来避免重复求解。在实际应用中,不同的算法适用于不同的问题,需要结合具体情况进行选用。