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

力扣刷题DAY10(动态规划-线性DP)

一、最长公共子序列

1143. 最长公共子序列

(一)灵茶山艾府

最长公共子序列 编辑距离【基础算法精讲 19】

定义:D[i][j]表示text1的前i个字符和text2的前j个字符的LCS。

然后需要考虑两个问题:

因此得到递推式:

(二)邋遢大哥233

[轻松掌握动态规划]5.最长公共子序列 LCS

最终代码:

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n = text1.size();
        int m = text2.size();
        vector<vector<int>> f(n + 1, vector<int>(m + 1, 0));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (text1[i - 1] == text2[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][m];
    }
};

复杂度分析

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

降维后(滚动数组):

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n = text1.size();
        int m = text2.size();
        vector<int> f(m + 1, 0);
        for (int i = 1; i <= n; i++) {
            int temp = 0; // 保存f[i-1][j-1]
            for (int j = 1; j <= m; j++) {
                int pre = f[j]; // 保存这一行的f[j]方便作为左上角
                if (text1[i - 1] == text2[j - 1])
                    f[j] = temp + 1;
                else
                    f[j] = max(f[j], f[j - 1]);
                temp = pre; // 成为下一行的左上角
            }
        }
        return f[m];
    }
};

复杂度分析

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

二、编辑距离

 72. 编辑距离

代码:

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n = word1.size();
        int m = word2.size();
        vector<vector<int>> f(n + 1, vector<int>(m + 1, 0));
        for (int i = 0; i <= m; i++)
            f[0][i] = i;
        for (int i = 0; i <= n; i++)
            f[i][0] = i;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (word1[i - 1] != word2[j - 1])
                    f[i][j] =
                        min(min(f[i - 1][j], f[i][j - 1]), f[i - 1][j - 1]) + 1;
                else
                    f[i][j] = f[i - 1][j - 1];
            }
        }
        return f[n][m];
    }
};

复杂度分析

  • 时间复杂度:O(nm),其中 n 为 s 的长度,m 为 t 的长度。
  • 空间复杂度:O(nm)。

降维后(滚动数组):

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n = word1.size();
        int m = word2.size();
        vector<int> f(m + 1, 0);
        for (int i = 0; i <= m; i++)
            f[i] = i;
        for (int i = 1; i <= n; i++) {
            int pre = f[0]; // pre 保存 f[i-1][j-1],初始为 f[i-1][0] = i-1
            f[0] = i;       // 更新当前行的 f[i][0] = i
            for (int j = 1; j <= m; j++) {
                int temp = f[j]; // 保存本次f[j],方便保留为左上角
                if (word1[i - 1] != word2[j - 1])
                    f[j] = min(min(f[j], f[j - 1]), pre) + 1;
                else
                    f[j] = pre;
                pre = temp; // pre成为左上角
            }
        }
        return f[m];
    }
};

易错点:

int pre = f[0]; // pre 保存 f[i-1][j-1],初始为 f[i-1][0] = i-1
f[0] = i;       // 更新当前行的 f[i][0] = i
  1. 降维后,每行的f[0](最左边一列)也是要随时更新的。
  2. 而pre要履行它的职责就是保存左上角的数,而对于每一行刚开始的时候,就是保存f[0]。

复杂度分析

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

相关文章:

  • rcore day6
  • [ctfshow web入门] web23
  • cdw2: TypeScript
  • 牛客网:树的高度 ← 根节点为 0 号节点
  • 脚本启动 Java 程序
  • 工程师 - FTDI SPI converter
  • async/await 异步编程
  • 将飞帆制作的网页作为 div 集成到自己的网页中
  • C语言之九九乘法表
  • PCL拟合空间3D圆周 fit3DCircle
  • 数智孪生:制造业转型的驱动力
  • 4月8日日记
  • YOLOv11改进 | YOLOv11引入MobileNetV4
  • I/O进程3
  • 【STL】list介绍(附与vector的比较)
  • 硅谷甄选项目笔记
  • 递归实现排列型枚举 Java
  • Vue框架的编译器优化
  • 利用rpm编译工具mock生成精简容器镜像及源码编译全流程解析
  • CSS 学习提升网站或者项目