IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【LeetCode】Day67-判断子序列 & 编辑距离 -> 正文阅读

[数据结构与算法]【LeetCode】Day67-判断子序列 & 编辑距离

题目1

392. 判断子序列【简单】

题解

暴力双指针

很简单,不多说了

class Solution {
    public boolean isSubsequence(String s, String t) {
        int m=s.length(),n=t.length(),i=0;
        for(int j=0;i<m && j<n;j++){
            if(s.charAt(i)==t.charAt(j))
                i++;
        }
        return i==m;
    }
}

时间复杂度: O ( m + n ) O(m+n) O(m+n)

空间复杂度: O ( 1 ) O(1) O(1)

动态规划

暴力其实就挺简单的了…而且复杂度也不错,但是官解中还给了动态规划的解法,刚开始不理解,后来看到评论里说的,假如有x条s要处理,此时双指针复杂度为 O ( x ( t l + s l ) ) O(x(tl+sl)) O(x(tl+sl)),但是动态规划复杂度只有 O ( x t l + s l ) O(xtl+sl) O(xtl+sl),恍然大悟

  1. 状态定义:dp[i][j] 表示字符串 t 中从位置 i 开始往后26个字母中每个字母第一次出现的位置
  2. 状态转移方程:如果 t[i] 就是 ‘a’+j,那么 dp[i][j]=i,否则 ‘a’+j 出现在位置 i+1 开始往后,即 dp[i][j]=dp[i+1][j]
    (1)t[i]==‘a’+j:dp[i][j] = i
    (2)t[i] !=‘a’+j:dp[i][j] = dp[i+1][j]
  3. 遍历顺序:因为遍历到 i 时,i+1必须有值,因此要从后向前遍历;j 从0到25
  4. 初始条件:dp[tl][i]=tl,表示t中不含该字母
class Solution {
    public boolean isSubsequence(String s, String t) {
        int sl=s.length(),tl=t.length();
        int dp[][]=new int[tl+1][26];
        //初始化dp,26个字母在t中的位置设置为tl,表示t中不存在该字母
        for(int i=0;i<26;i++)
            dp[tl][i]=tl;
        //26个字母在t中的位置
        for(int i=tl-1;i>=0;i--){
            for(int j=0;j<26;j++){
                if(t.charAt(i)=='a'+j)
                    dp[i][j]=i;
                else
                    dp[i][j]=dp[i+1][j];
            }
        }
        /*判断t中是否含有s*/
        int add=0;//t中字符下标
        //遍历s中字母i
        for(int i=0;i<sl;i++){
            //t中没有s[i]
            if(dp[add][s.charAt(i)-'a']==tl)
                return false;
            //t挪到t[s[i]]的下一个位置
            add=dp[add][s.charAt(i)-'a']+1;
        }
        return true;
    }
}

时间复杂度: O ( 26 ? t l + s l ) O(26*tl+sl) O(26?tl+sl)

空间复杂度: O ( 26 ? t l ) O(26*tl) O(26?tl)

题目2

72. 编辑距离【困难】

题解

又是一道经典的困难题…完全没思路…熟读背诵吧

首先分析操作类型,题目给出了三种:插入、删除和修改,那么对于两个单词A和B来说,一共有六种操作方式,但是会发现三个等式:

  1. 插入A=删除B(如 A=dog,B=doge)
  2. 删除A=插入B(如 A=doge,B=dog)
  3. 修改A=修改B(如 A=cat,B=bat)

所以可将六种操作方式简化为三种,插入A,插入B,修改A

再来看一下如何把问题转化为规模较小的子问题,假设A=horse,B=ros,

  1. 插入A:假设horse到ro的编辑距离为a,那么horse到ros的编辑距离不超过a+1,因为ro到ros只需要一步插入字符’s’(horse->ro->ros)
  2. 插入B:假设hors到ros的编辑距离为b,那么horse到ros的编辑距离不超过b+1,因为hors到horse只需要一步插入字符’e’(ros->hors->horse)
  3. 修改A:假设hors到ro的编辑距离为c,那么horse到ros的编辑距离不超过c+1,因为roe到ros只需要一步将’e’替换为’s’(horse->roe->ros)

所以从 horse 变成 ros 的编辑距离应该为 min(a + 1, b + 1, c + 1)

最后来讨论一下动态规划的4个重要问题

  1. 状态定义:dp[i][j] 表示 A 的前 i 个字母和 B 的前 j 个字母之间的编辑距离。
  2. 状态转移方程

    其中D[i][j-1] 为 A 的前 i 个字符和 B 的前 j - 1 个字符编辑距离的子问题。即对于B[j],我们在A的末尾添加了一个同样的字符 (->A和B最后一个字符相同,同时删去这个字符编辑距离也相同,对于A来说只是删除了添加的字符,因此还是i,对于B来说,删掉了末尾的字符,因此为j-1),则D[i][j] 最小可以为 D[i][j-1] + 1 (+1是在A末尾添加字符的那步操作)
    D[i-1][j] 为 A 的前 i - 1 个字符和 B 的前 j 个字符编辑距离的子问题。即对于A[i],我们在B的末尾添加了一个同样的字符,则D[i][j] 最小可以为 D[i-1][j] + 1;
    D[i-1][j-1] 为 A 前 i - 1 个字符和 B 的前 j - 1 个字符编辑距离的子问题。即对于 B [j],我们修改 A [i] 使它们相同,那么 D[i][j] 最小可以为 D[i-1][j-1] + 1。特别地,如果 A 的第 i 个字符和 B 的第 j 个字符原本就相同,那么我们实际上不需要进行修改操作。在这种情况下,D[i][j] 最小可以为 D[i-1][j-1]。

借用官解的图举个例子:
在这里插入图片描述

  1. 初始条件:dp[i][0]=i,表示对word1执行 i 次删除操作;dp[0][j]=j,表示对word2执行 j 次删除操作;
  2. 返回值:dp[n1-1][n2-1]
class Solution {
    public int minDistance(String word1, String word2) {
        int n1=word1.length(),n2=word2.length();
        //dp初始化
        int dp[][]=new int[n1+1][n2+1];
        for(int i=0;i<=n1;i++)
            dp[i][0]=i;//空字符到word1[0..i]只需插入i个字符
        for(int j=0;j<=n2;j++)
            dp[0][j]=j;
        for(int i=1;i<=n1;i++){
            for(int j=1;j<=n2;j++){
                int mod=dp[i-1][j-1];
                if(word1.charAt(i-1)==word2.charAt(j-1))
                    mod--;//最后一个字符相同,直接为dp[i-1][j-1],不用+1
                dp[i][j]=Math.min(dp[i-1][j],Math.min(dp[i][j-1],mod))+1;
            }
        }
        return dp[n1][n2];
    }
}

时间复杂度: O ( m n ) O(mn) O(mn)

空间复杂度: O ( m n ) O(mn) O(mn)

p.s 最近涉及字符串的动态规划简直是我的软肋,完全不会做

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 18:28:41  更:2022-05-24 18:29:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 1:13:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码