day55 补

news2024/12/28 20:48:31

392.判断子序列

力扣题目链接(opens new window)

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

示例 1:

  • 输入:s = "abc", t = "ahbgdc"
  • 输出:true

示例 2:

  • 输入:s = "axc", t = "ahbgdc"
  • 输出:false

提示:

  • 0 <= s.length <= 100
  • 0 <= t.length <= 10^4

两个字符串都只由小写字符组成。

#算法公开课

《代码随想录》算法视频公开课 (opens new window):动态规划,用相似思路解决复杂问题 | LeetCode:392.判断子序列 (opens new window),相信结合视频再看本篇题解,更有助于大家对本题的理解

#思路

(这道题也可以用双指针的思路来实现,时间复杂度也是O(n))

这道题应该算是编辑距离的入门题目,因为从题意中我们也可以发现,只需要计算删除的情况,不用考虑增加和替换的情况。

所以掌握本题的动态规划解法是对后面要讲解的编辑距离的题目打下基础

动态规划五部曲分析如下:

  1. 确定dp数组(dp table)以及下标的含义

dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]

注意这里是判断s是否为t的子序列。即t的长度是大于等于s的。

有同学问了,为啥要表示下标i-1为结尾的字符串呢,为啥不表示下标i为结尾的字符串呢?

为什么这么定义我在 718. 最长重复子数组 (opens new window)中做了详细的讲解。

其实用i来表示也可以!

但我统一以下标i-1为结尾的字符串来计算,这样在下面的递归公式中会容易理解一些,如果还有疑惑,可以继续往下看。

  1. 确定递推公式

在确定递推公式的时候,首先要考虑如下两种操作,整理如下:

  • if (s[i - 1] == t[j - 1])
    • t中找到了一个字符在s中也出现了
  • if (s[i - 1] != t[j - 1])
    • 相当于t要删除元素,继续匹配

if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;,因为找到了一个相同的字符,相同子序列长度自然要在dp[i-1][j-1]的基础上加1(如果不理解,在回看一下dp[i][j]的定义

if (s[i - 1] != t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];

其实这里 大家可以发现和 1143.最长公共子序列 (opens new window)的递推公式基本那就是一样的,区别就是 本题 如果删元素一定是字符串t,而 1143.最长公共子序列 是两个字符串都可以删元素。

  1. dp数组如何初始化

从递推公式可以看出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]是一定要初始化的。

这里大家已经可以发现,在定义dp[i][j]含义的时候为什么要表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]

因为这样的定义在dp二维矩阵中可以留出初始化的区间,如图:

392.判断子序列

如果要是定义的dp[i][j]是以下标i为结尾的字符串s和以下标j为结尾的字符串t,初始化就比较麻烦了。

dp[i][0] 表示以下标i-1为结尾的字符串,与空字符串的相同子序列长度,所以为0. dp[0][j]同理。

vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));

1

  1. 确定遍历顺序

同理从递推公式可以看出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],那么遍历顺序也应该是从上到下,从左到右

如图所示:

392.判断子序列1

  1. 举例推导dp数组

以示例一为例,输入:s = "abc", t = "ahbgdc",dp状态转移图如下:

392.判断子序列2

dp[i][j]表示以下标i-1为结尾的字符串s和以下标j-1为结尾的字符串t 相同子序列的长度,所以如果dp[s.size()][t.size()] 与 字符串s的长度相同说明:s与t的最长相同子序列就是s,那么s 就是 t 的子序列。

图中dp[s.size()][t.size()] = 3, 而s.size() 也为3。所以s是t 的子序列,返回true。

动规五部曲分析完毕,C++代码如下:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));
        for (int i = 1; i <= s.size(); i++) {
            for (int j = 1; j <= t.size(); j++) {
                if (s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                else dp[i][j] = dp[i][j - 1];
            }
        }
        if (dp[s.size()][t.size()] == s.size()) return true;
        return false;
    }
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14

  • 时间复杂度:O(n × m)
  • 空间复杂度:O(n × m)

#总结

这道题目算是编辑距离的入门题目(毕竟这里只是涉及到减法),也是动态规划解决的经典题型。

这一类题都是题目读上去感觉很复杂,模拟一下也发现很复杂,用动规分析完了也感觉很复杂,但是最终代码却很简短。

在之前的题目讲解中,我们讲了 1143.最长公共子序列 (opens new window),大家会发现 本题和 1143.最长公共子序列 的相似之处。

编辑距离的题目最能体现出动规精髓和巧妙之处,大家可以好好体会一下。

#其他语言版本

#Java:

class Solution {
    public boolean isSubsequence(String s, String t) {
        int length1 = s.length(); int length2 = t.length();
        int[][] dp = new int[length1+1][length2+1];
        for(int i = 1; i <= length1; i++){
            for(int j = 1; j <= length2; j++){
                if(s.charAt(i-1) == t.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else{
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        if(dp[length1][length2] == length1){
            return true;
        }else{
            return false;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/995140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MFC】Button控件美化(自绘)

在MFC中Button控件不能通过OnCtlColor&#xff08;&#xff09;函数对外观做太多的改变。 HBRUSH C按钮控件自绘Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {HBRUSH hbr CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);switch (pWnd->GetDlgCtrlID()){case ID…

【已解决】ORA-00001: unique constraint (USR_JXZX_DSJKF_MODEL.SYS_C00912833) violated

已解决&#xff1a; nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (USR_JXZX_DSJKF_MODEL.SYS_C00912833) violated 问题 学号主键ID重复了 思路 在 Oracle 中&#xff0c;可以使用以下方法找出重复的主键&#…

Vue中实现3D得球自动旋转

具体实现 安装echarts 在终端下安装echarts npm install -D echarts 安装echarts-gl 在终端下安装echarts-gl npm install -D echarts-gl earth3D组件 earth3D.vue <template><div class"globe3d-earth-container" ><div class"globe3d-earth&qu…

桉木做的建筑模板质量评价

桉木作为一种常见的建筑模板材料&#xff0c;以其独特的特性在建筑行业中得到广泛应用。然而&#xff0c;评估桉木建筑模板的质量是确保建筑项目成功的关键因素之一。本文将对桉木建筑模板的质量进行评价&#xff0c;从材料特性、强度和耐久性等方面进行分析。 首先&#xff0c…

Pinyin4j介绍和简单使用

前言 Pinyin4j是一个Java库&#xff0c;用于将汉字转换为拼音。它是由中国清华大学的Tsinghua University和中国科学院计算技术研究所的研究人员开发的。Pinyin4j可以用于Java应用程序中&#xff0c;以便在需要时将汉字转换为拼音。例如&#xff0c;它可以用于中文输入法、文本…

大模型tokenizer流式响应解决词句连贯性问题

大模型tokenizer词句连贯性问题 现象 from transformers import LlamaTokenizerFast import numpy as nptokenizer LlamaTokenizerFast.from_pretrained("heilerich/llama-tokenizer-fast") origin_prompt "Hi, Im Minwoo Park from seoul, korea." id…

使用 multiprocessing 多进程处理批量数据

示例代码 import multiprocessingdef process_data(data):# 这里是处理单个数据的过程return data * 2# 待处理的数据 data [1, 2, 3, 4, 5]def normal_func():# 普通处理方式result []for obj in data:result.append(process_data(obj)return resultdef parallel_func():# …

JavaScript编程语法作业

目录 目录 前言 思维导图 1&#xff0c;作业资源 2&#xff0c;if语句练习 2.1代码解读: 2.2,结果展示: 3&#xff0c;switch语句练习 3.1,代码解读: 3.2,结果展示: 4.while循环练习 4.1,代码解读: 4.2.结果展示: 5.do-while循环练习 5.1,代码解读: 5.2,结果展…

STM32 CAN/CANFD软件快速配置(HAL库版本)

STM32 CAN/CANFD软件快速配置&#xff08;HAL库版本&#xff09; 目录 STM32 CAN/CANFD软件快速配置&#xff08;HAL库版本&#xff09;前言1 软件编程1.1 建立工程1.2 初始化1.2.1 引脚设置1.2.2 CAN基本参数设置1.2.3 CAN收发初始化设置1.2.4 中断设置 1.3 CAN发送1.4 CAN接收…

自定义Dynamics 365实施和发布业务解决方案 3. 开箱即用自定义

在本章中,您将开始开发SBMA会员应用程序。在开发的最初阶段,主要关注开箱即用的定制。在第2章中,我们讨论了如何创建基本解决方案的细节,在本章中,将创建作为解决方案补丁的基本自定义,并展示将解决方案添加到源代码管理和目标环境的步骤。 表单自定义 若要开始表单自定…

连续 3 年 40% 增长 续费率近 110%:纷享销客增长的底层逻辑

经营管理没有一招鲜&#xff0c;持续增长的底层逻辑&#xff0c;就是持续稳定的建设&#xff0c;不被外界所干扰。 笔记整理 | 张保文 SaaS 增长&#xff0c;比拼的是战略、组织、人才、市场、销售、客户成功等全价值链的基本功。连续 3 年 40% 增长&#xff0c;续费率近 110%…

【图解RabbitMQ-5】RabbitMQ Web管控台图文介绍

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

C++ 结构体

前文 C中的结构体是一种非常有用的数据类型&#xff0c;它允许我们将不同的变量组合在一起&#xff0c;形成一个自定义的数据结构。 结构体在C中的应用非常广泛&#xff0c;它可以用来表示和管理各种实体、对象或数据的属性。比如&#xff0c;在一个学生管理系统中&#xff0c…

2.2 Java中的变量

1. 变量与赋值 在程序运行期间&#xff0c;随时可能产生一些临时数据&#xff0c;应用程序会将这些数据保存在内存单元中&#xff0c;每个内存单元都用一个标识符标识&#xff0c;这些用于标识内存单元的标识符就称为变量&#xff0c;内存单元中存储的数据就是变量的值。 下面…

C++day1---9.6

思维导图&#xff1a; 1.使用cout完成输出斐波那契前20项的内容 #include <iostream>using namespace std;int main() {int a 1;int b 0;int sum 1;int arr[20] {0};for(int i0; i<20; i){arr[i] sum; //存放最新值sum ab; //更新sumb a; …

windows mysql弹出黑框处理

现象 处理方式 点击禁用即可 以后就不会再出现了

【Arduino30】DS1302时钟芯片模拟值实验

硬件准备 DS1302芯片&#xff1a;1片 32.768kHz晶振&#xff1a;1个 面包板&#xff1a;1个 杜邦线&#xff1a;若干 硬件连线 软件程序 #include <DS1302.h> //头文件//定义引脚 const int rst_pin 5; const int date_pin 6; const int sclk_pin 7;//将DS1302实…

ARTS 2023.8.21-2023.8.27 (第一周)

ARTS 2023.8.21-2023.8.27 &#xff08;第一周&#xff09; &#x1f4a1;ARTS&#xff1a; A&#xff1a;至少每周完成一道Leecode的算法题&#xff1b; R&#xff1a;阅读并点评至少一篇英文技术文章&#xff1b; T&#xff1a;学习至少一个技术技巧&#xff1b; S&#xff…

Tina Ti 计算电路中的参数

如图所示 计算每个节点的参数 通过这个工具&#xff0c;就算你不知道电路的原理&#xff0c;电路网络分析&#xff0c;你都可以计算出理论值是多少。

PTA作业笔记——简单的输入输出

PTA前十题 7-2 输入输出整数7-3 输入输出单精度实数7-4 输入输出双精度实数7-5 输入输出字符7-6 整数的各种形式输出7-7 混合无间隔输入输出7-8 日期格式化7-9 区位码输入法 写在前面&#xff1a;不是很难的题目直接放上代码&#xff0c;只作为记录 初学C语言的时候涉及到的输入…