C语言/数据结构动态规划题解:字符串变回文的最少操作次数——最长回文子序列(LPS)

问题描述

小明正在玩一个字符串拼图游戏,他有一个由小写字母组成的字符串。游戏规则允许他进行两种操作:1) 删除任意一个字符;2) 在任意位置插入任意一个小写字母。每次操作都会消耗1点能量。现在小明想要通过最少的操作次数,使得字符串变成回文串(即正着读和反着读都一样)。请你帮助小明计算最少需要多少次操作。

要求:

  1. 设计一个动态规划算法来计算最小操作次数。
  2. 算法的时间复杂度应为 O(n²),其中 n 是字符串的长度。

提示 :

最小操作次数等于字符串长度减去该字符串的最长回文子序列的长度。

例如,字符串 "abcda" 的最长回文子序列是 "aca" 或 "ada",长度为3,所以最小操作次数为 5 - 3 = 2。

你可以使用动态规划来求解最长回文子序列的长度。

测试样例

样例1:

输入:s = "abcda" 输出:2 解释:最长回文子序列为 "aca" 或 "ada",长度为3,所以最小操作次数为 5 - 3 = 2。一种可行方案是删除 'b' 和 'c'(2次操作)得到 "ada"。

样例2:

输入:s = "abcd" 输出:3 解释:最长回文子序列为 "a"(或 "b"、"c"、"d"),长度为1,所以最小操作次数为 4 - 1 = 3。一种可行方案是删除 'b'、'c'、'd'(3次操作)得到 "a"。

样例3:

输入:s = "a" 输出:0 解释:单个字符已经是回文串,最长回文子序列长度为1,所以最小操作次数为 1 - 1 = 0。

约束条件

  • 1 ≤ s.length ≤ 1000
  • 字符串 s 仅包含小写英文字母
  • 保证输入字符串非空

程序代码

#include <stdio.h>

#include <string.h>

int minOperations(char* s) {

int n = strlen(s);

if (n <= 1) return 0;

// dpij 表示 si..j 的最长回文子序列长度

int dp10001000;

// 初始化:单个字符长度为1

for (int i = 0; i < n; i++) {

dpii = 1;

}

// 按长度递增计算

for (int len = 2; len <= n; len++) {

for (int i = 0; i + len - 1 < n; i++) {

int j = i + len - 1;

if (si == sj) {

if (len == 2) {

dpij = 2;

} else {

dpij = dpi+1j-1 + 2;

}

} else {

dpij = (dpi+1j > dpij-1) ? dpi+1j : dpij-1;

}

}

}

int lps = dp0n-1;

return n - lps;

}

int main() {

printf("%d\n", minOperations("abcda")); // 2

printf("%d\n", minOperations("abcd")); // 3

printf("%d\n", minOperations("a")); // 0

return 0;

}

cpp 复制代码
#include <stdio.h>
#include <string.h>

int minOperations(char* s) {
    int n = strlen(s);
    if (n <= 1) return 0;
    
    // dp[i][j] 表示 s[i..j] 的最长回文子序列长度
    int dp[1000][1000];
    
    // 初始化:单个字符长度为1
    for (int i = 0; i < n; i++) {
        dp[i][i] = 1;
    }
    
    // 按长度递增计算
    for (int len = 2; len <= n; len++) {
        for (int i = 0; i + len - 1 < n; i++) {
            int j = i + len - 1;
            
            if (s[i] == s[j]) {
                if (len == 2) {
                    dp[i][j] = 2;
                } else {
                    dp[i][j] = dp[i+1][j-1] + 2;
                }
            } else {
                dp[i][j] = (dp[i+1][j] > dp[i][j-1]) ? dp[i+1][j] : dp[i][j-1];
            }
        }
    }
    
    int lps = dp[0][n-1];
    return n - lps;
}

int main() {
    printf("%d\n", minOperations("abcda"));  // 2
    printf("%d\n", minOperations("abcd"));   // 3
    printf("%d\n", minOperations("a"));      // 0
    return 0;
}

运行结果

相关推荐
ZhengEnCi8 小时前
GPT-6 Astra 爆改 Qwen 权重真有那么神吗:权重空间编程 0.016% 参数的真相
算法·架构
罗西的思考8 小时前
【轻量化复刻大模型 / KIMI K3】KDA(Kimi Delta Attention):并行
人工智能·算法·机器学习
蹊黎8 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
夜不会漫长10 小时前
C++:红黑树
数据结构·算法
爱聊灵光的维C10 小时前
从看见世界到重构认知:在视觉与硬件的交汇处,寻找我们这代人的北极星
c语言·物联网·计算机视觉·重构·硬件工程·射频工程
AI+程序员在路上10 小时前
RV1126B 上支持的模型及全流程应用--从CNN及语音到 LLMVLM 与跨平台选型
linux·c语言·人工智能
AI备案指南-满满11 小时前
算法备案审核不通过,一般是什么原因?
java·人工智能·算法·大模型备案·算法备案·大模型登记
Ramble_Naylor11 小时前
Rust深度解读:Send 与 Sync 的本质与线程安全边界
python·算法·rust
秋天的怀念_David11 小时前
算法一千零一夜 · 第二十三夜 电力民生写成的曲线
java·程序人生·算法
不一样的故事12611 小时前
NB/T 47013.8-2015 附录D 吸枪技术
人工智能·经验分享·算法