当前位置: 首页 > news >正文

力扣刷题DAY12(动态规划-区间DP)

一、最长回文子序列

516. 最长回文子序列

(一)动态规划

对于一个子序列而言,如果它是回文子序列,并且长度大于 2,那么将它首尾的两个字符去除之后,它仍然是个回文子序列。因此可以用动态规划的方法计算给定字符串的最长回文子序列。

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        vector<vector<int>> f(n, vector<int>(n, 0));
        for (int i = n - 1; i >= 0; i--) {
            f[i][i] = 1;
            for (int j = i + 1; j < n; j++) {
                if (s[i] == s[j])
                    f[i][j] = f[i + 1][j - 1] + 2;
                else
                    f[i][j]=max(f[i+1][j],f[i][j-1]);            
            }
        }
        return f[0][n - 1];
    }
};

复杂度分析

  • 时间复杂度:O(n2)。
  • 空间复杂度:O(n2)。

问:如何思考循环顺序?什么时候要正序,什么时候要倒序?

答:这里有一个通用的做法:盯着状态转移方程,想一想,要计算 f[i][j],必须先把 f[i+1][⋅] 算出来,那么只有 i 从大到小枚举才能做到。而对于j来说,要计算 f[i][j],必须先把 f[⋅][j-1] 算出来,那么只有 j 从小到大枚举才能做到。此外,j在i右边,所以在第二层循环的时候,j从i+1开始。

(二)空间优化(滚动数组)

跟最长公共子序列的优化很相似,要保存一些特殊的值传递到下一层循环。

观察到:

  • 状态5的f[j]来自已经更新的f[j-1]和未更新的f[j],所以f[j] = max(f[j - 1], f[j]);
  • 状态6的f[j]来自未更新的f[j-1],但是此时f[j-1]已更新,所以需要每次更新f[j]的时候存一下,传到下次j处。
  • 每次刚开始新的一行时,左下角是0,需要特殊初始化一下pre。
  • 每次刚开始新的一行时,第一个数都是1,需要初始化一下f[i]。
class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n = s.size();
        vector<int> f(n, 0);
        for (int i = n - 1; i >= 0; i--) {
            int pre = 0; // 每一行新开始的时候,左下角都是0
            f[i] = 1;
            for (int j = i + 1; j < n; j++) {
                int temp = f[j]; // 记录此时的f[j],以便成为左下角
                if (s[i] == s[j])
                    f[j] = pre + 2;
                else
                    f[j] = max(f[j - 1], f[j]);
                pre = temp; // 保存下一个j的左下角
            }
        }
        return f[n - 1];
    }
};

复杂度分析

  • 时间复杂度:O(n2)。
  • 空间复杂度:O(n)。

(三)倒序 + 最长公共子序列

回文子序列本质就是:该字符串与自己的逆序串求最长公共子序列。

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        string rs = s;
        reverse(rs.begin(), rs.end());
        int n = s.size();
        vector<vector<int>> f(n + 1, vector<int>(n + 1, 0));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (s[i - 1] == rs[j - 1])
                    f[i][j] = f[i - 1][j - 1] + 1;
                else
                    f[i][j] = max(f[i - 1][j], f[i][j - 1]);
            }
        }
        return f[n][n];
    }
};

复杂度分析

  • 时间复杂度:O(n2)。
  • 空间复杂度:O(n2)。 

二、  最长回文子串

5. 最长回文子串

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        vector<vector<bool>> f(n, vector<bool>(n, false));
        int max = 1;
        int start = 0;
        for (int i = 0; i < n; i++)
            f[i][i] = true;
        for (int j = 1; j < n; j++) {
            for (int i = 0; i < n-1 && i < j; i++) {
                if (s[i] != s[j])
                    f[i][j] = false;
                else {
                    if (j - i < 3)
                        f[i][j] = true;
                    else
                        f[i][j] = f[i + 1][j - 1];
                }
                if (f[i][j] && j - i + 1 > max) {
                    max = j - i + 1;
                    start = i;
                }
            }
        }
        return s.substr(start, max);
    }
};

复杂度分析

  • 时间复杂度:O(n2)。
  • 空间复杂度:O(n2)。 

注意到两个题的区别:

子串问题要保证区间整体连续是回文,必须递归依赖内部状态;而子序列只要找出最优的、不连续的组合,状态转移更“宽松”


文章转载自:

http://D37ytDxc.zrLms.cn
http://lQYoRd2b.zrLms.cn
http://8zaPyAFc.zrLms.cn
http://0SYW4Mnk.zrLms.cn
http://7flkbLjk.zrLms.cn
http://rgnghEqv.zrLms.cn
http://cbDudMCp.zrLms.cn
http://TuhgoGY2.zrLms.cn
http://fxtnwage.zrLms.cn
http://VD9gS3HW.zrLms.cn
http://e2dzt1Y3.zrLms.cn
http://roO3QxBl.zrLms.cn
http://OTPANTAe.zrLms.cn
http://Kw5JNzNq.zrLms.cn
http://X9b9Z95X.zrLms.cn
http://TMat7gyY.zrLms.cn
http://t8129E8L.zrLms.cn
http://I4DEXnW0.zrLms.cn
http://gYag41PO.zrLms.cn
http://WFNPkIdF.zrLms.cn
http://Uf7LmqJQ.zrLms.cn
http://OzetX8ZY.zrLms.cn
http://2nFeXnap.zrLms.cn
http://KyrWmm2W.zrLms.cn
http://vtPG0Vel.zrLms.cn
http://9OsWlqeQ.zrLms.cn
http://2MBiFOzz.zrLms.cn
http://cpShhrvE.zrLms.cn
http://6IiLliev.zrLms.cn
http://w3VszVHK.zrLms.cn
http://www.dtcms.com/a/128246.html

相关文章:

  • AUTO-RAG: AUTONOMOUS RETRIEVAL-AUGMENTED GENERATION FOR LARGE LANGUAGE MODELS
  • 用Java实现O(n)时间复杂度查找最长连续序列
  • 【特权FPGA】之SRAM读写
  • C语言--汉诺塔问题
  • 软考 系统架构设计师系列知识点之杂项集萃(50)
  • asm汇编源代码之按键处理相关函数
  • 《JVM考古现场(十八):造化玉碟·用字节码重写因果律的九种方法》
  • 操作系统:线程间同步之事件集
  • 【人脸识别中的“类内差异”和“类间差异】
  • 关闭当前微信小程序解决方案
  • FFMPEG和opencv的编译
  • 音视频之H.265/HEVC编码框架及编码视频格式
  • Vue3.5 企业级管理系统实战(十四):动态主题切换
  • 行星际激波数据集 (2023)
  • 利用python从零实现Byte Pair Encoding(BPE)
  • Node.js中fs模块详解
  • 浏览器多开
  • MCP遇见Web3:从边缘计算到去中心化的无限想象
  • 【NLP解析】多头注意力+掩码机制+位置编码:Transformer三大核心技术详解
  • 自动驾驶技术关键技术梳理
  • 如何使用 Grafana 连接 Easyearch
  • 【HCIP】GRE VPN实验笔记
  • 遵循IEC 62304:构建安全可靠的医疗器械软件
  • [python]通过whl文件安装pyheif安装教程和简单使用案例
  • Linux进程通信入门:匿名管道的原理、实现与应用场景
  • 部署NFS版StorageClass(存储类)
  • Unity6国际版下载
  • Linux 一文快速入门
  • ChromeOS 135 版本更新
  • 【NumPy科学计算引擎:从基础操作到高性能实践】