想要精通算法和SQL的成长之路 - 判断子序列问题

news2024/11/24 6:41:40

想要精通算法和SQL的成长之路 - 判断子序列问题

  • 前言
  • 一. 判断子序列
    • 1.1 动态规划做法
    • 1.2 双指针
  • 二. 不同的子序列

前言

想要精通算法和SQL的成长之路 - 系列导航

一. 判断子序列

原题链接
给定字符串 st ,判断 s 是否为 t 的子序列。

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

1.1 动态规划做法

这个题目其实是使用双指针会更加简单明了点的。我这里是放在动态规划里面去学习的。因此我先来说些动态规划怎么做。大家可以先看下这篇文章最长序列问题

里面对于满足以下两种条件的:

  • 存在两个对象的。
  • 可以删除某个字符串的(不连续)。

可以发现写的代码都是一个风格。思路:

1.我们定义dp[i][j]:在s 中以i-1为结尾。在t中以j-1为结尾的相同子序列长度。

看到这里的朋友可能想问了。最长公共子序列这个题目中,定义的是区间,为什么这里就是以xxx为结尾呢?

注意:

  1. 我们不再是求得ts的重复序列部分。而是判断s是否可以作为t的一个子序列。
  2. 换句话就是,s对于最长公共共子序列这个题目来说,其长度已经定死了。我们无需关系其区间问题。

2.如果s[i]t[j] 相等。那么dp[i][j] = dp[i-1][j-1] +1
3.如果s[i]t[j] 不相等。也就是说我们需要在t这个字符串中删除元素了。即dp[i][j] = dp[i][j-1]

4.最终结果来看,判断子序列的标准是啥?就是相同子序列的长度(dp[i][j])等于字符串s的长度。

写成代码就是:

public boolean isSubsequence(String s, String t) {
    int[][] dp = new int[s.length() + 1][t.length() + 1];
    for (int i = 1; i <= s.length(); i++) {
        for (int j = 1; j <= t.length(); 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];
            }
        }
    }
    return dp[s.length()][t.length()] == s.length();
}

1.2 双指针

思路:

  1. 我们定义两个下标indexSindexT,分别在st中进行遍历。
  2. 循环操作:如果s[indexS]t[indexT] 相等,那么两个指针同时往后移动。否则,移动indexT指针。
  3. 循环条件:两个指针都不能越界。
  4. 判断子序列条件:indexS指针到达的位置就是字符串s的长度。说明在字符串t中找到了字符串s的子序列。
public boolean isSubsequence(String s, String t) {
    int indexS = 0, indexT = 0;
    while (indexS < s.length() && indexT < t.length()) {
        if (s.charAt(indexS) == t.charAt(indexT)) {
            indexS++;
        }
        indexT++;
    }

    return indexS == s.length();
}

二. 不同的子序列

原题链接
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,“ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)

题目数据保证答案符合 32 位带符号整数范围。

示例 1:

  • 输入:s = “rabbbit”, t = “rabbit”
  • 输出:3
  • 解释:如下图所示, 有 3 种可以从 s 中得到 “rabbit” 的方案(看下划线)。
    在这里插入图片描述

先小提醒一下:

  • 第一题中:st的子序列。
  • 第二题中:ts的子序列。

思路:

1.dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]


2.递归公式的推导。需要注意的一点就是:我们是拿 s 字符串中的字符去匹配 t 字符串。

举例:我们可以从后往前进行匹配。让可匹配的字符串越来越小。让问题缩小化。

  • s:rabbb
  • t:rabb

如果s[i] == t[j],有两种情况:
第一种情况:我们可以用s[i]去匹配t[t,length]
如果s[i] != t[j],即s[i]这个字符不能用来匹配,dp[i][j]代表的子序列个数,需要继承上一个值,即dp[i-1][j]

那么这部分代码就是:

for (int i = 1; i <= s.length(); i++) {
    for (int j = 1; j <= t.length(); j++) {
        if (s.charAt(i - 1) == t.charAt(j - 1)) {
            dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
        } else {
            dp[i][j] = dp[i - 1][j];
        }
    }
}

紧接着就是dp数组的初始化问题。上面的分析是将字符串缩短,从后往前进行分析的。那么缩短到一定程度,可分为两种情况:

  • t(子串)变成空串了,那么s为了匹配它,只有一种情况,就是把s本身变成空串。因此方式数为1。
  • s变成空串了,但是t还不是(因为设定上t是子串,t为空串的时候,s肯定不是空串),此时s无法匹配t,因此方式数为0。

即:

// s为空串,t非空,s无法匹配,方式数为0,这段代码可以不写,因为int数组默认值就是0
for (int j = 0; j < t.length(); j++) {
    dp[0][j] = 0;
}
// t为空串,s非空,s只有将其本身变空,方式数为1
for (int i = 0; i < s.length(); i++) {
    dp[i][0] = 1;
}

返回值:得到以s.len为结尾,包含子序列t的方式数。即dp[s.length()][t.length()] 。最终代码:

public int numDistinct(String s, String t) {
    int[][] dp = new int[s.length() + 1][t.length() + 1];
    // s为空串,t非空,s无法匹配,方式数为0,这段代码可以不写,因为int数组默认值就是0
    for (int j = 0; j < t.length(); j++) {
        dp[0][j] = 0;
    }
    // t为空串,s非空,s只有将其本身变空,方式数为1
    for (int i = 0; i < s.length(); i++) {
        dp[i][0] = 1;
    }
    for (int i = 1; i <= s.length(); i++) {
        for (int j = 1; j <= t.length(); j++) {
            // 如果两个元素相等
            if (s.charAt(i - 1) == t.charAt(j - 1)) {
                // 两种情况,使用s[i] 和不使用s[i] 去匹配
                dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
            } else {
                // 否则无法匹配,继承上一个方式数
                dp[i][j] = dp[i - 1][j];
            }
        }
    }
    // 得到以 s.length() 为结尾,出现字符串t的方式数
    return dp[s.length()][t.length()];
}

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

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

相关文章

阿里p8实战总结SpringCloud微服务分布式系统文档

前言 有人调侃我们说&#xff1a; 程序员不如送外卖。送外卖是搬运食物&#xff0c;自己是搬运代码&#xff0c;都不产出新的东西……透支体力&#xff0c;又消耗健康&#xff0c;可替代性极强&#xff0c;30岁之后就要面临被优化的危险……想跳槽&#xff0c;但是更高的平台…

Interval Envision图像库,非常强大的图像功能

Interval Envision图像库被认为具有增强Borland和Embarcadero Delphi的能力&#xff0c;并为用户和开发人员提供非常强大的图像功能。该库能够为用户提供一个图像文件I/O&#xff0c;用于文件的流行格式、扫描、打印过程、ocr的接口&#xff0c;以及最终的图片处理&#xff0c;…

Linux文件系统——文件系统、挂载点、目录结构

目录 一、目录结构 1.1 基本介绍 1.2 详细说明目录作用 二、挂载点 一、目录结构 1.1 基本介绍 Linux是一切皆文件&#xff0c;将所用的东西当做文件处理 目录结构就是一个单一的树状结构 整个的目录树只有一个树根&#xff1a;/ 根目录 文件夹分门别类的放到根目录…

vue配置环境变量

vue配置环境变量目录概述需求&#xff1a;设计思路实现思路分析1.URL管理2.网页3.加载.env4.分析参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for c…

卷积神经网络kernel/filter/stride

【关于神经网络的学习】 【参考】&#xff1a;卷积核filter和kernal的区别 - 一杯明月 - 博客园 (cnblogs.com) 【参考】&#xff1a;(1条消息) 卷积神经网络的卷积核&#xff08;kernel&#xff09;、输入尺寸&#xff08;input&#xff09;、步长&#xff08;stride&#x…

[附源码]计算机毕业设计springboot学生疫情防控信息填报系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

使用frp进行内网穿透

frp概述 frp 是一个高性能的反向代理应用&#xff0c;可以帮助您轻松地进行内网穿透&#xff0c;对外网提供服务&#xff0c;支持 tcp, http, https 等协议类型&#xff0c;并且 web 服务支持根据域名进行路由转发。frp 采用 C/S 模式&#xff0c;将服务端部署在具有公网 IP 机…

Kafka - topic producer consumer 常用命令

Kafka常用命令 Topic相关 创建topic bin/kafka-topics.sh --create --zookeeper node02:2181 --replication-factor 1 --partitions 1 --topic testkafka3.3.1新版本就会提示不兼容&#xff0c;需要改用新版本 Exception in thread "main" joptsimple.Unrecogniz…

单链表初阶的两道基础题

初阶链表刷题翻转单链表&#xff08;链接在末尾&#xff09;链表的倒数第K个结点&#xff08;链接在末尾&#xff09;普通解法进阶解法注意&#xff01;&#xff01;&#xff01;学习的是解题的思维&#xff01; 翻转单链表&#xff08;链接在末尾&#xff09; 解题思路 如果给…

Java#31(不可变集合,Stream流和方法引用)

目录 一.创建不可变集合: 不可以被修改的集合 1.List接口创建不可变集合 2.Set接口创建不可变集合 3.Map接口创建不可变集合 二.Stream流 1.如何获取Stream流? 2.Stream流的中间方法 3.Stream流终结方法 三.方法引用 1.引用静态方法 2.引用成员方法 3.引用结构方法…

【Java学习】JavaWeb---Request Response

文章目录1. Request1. 1Request继承体系1.2 Request获取请求数据1.3 Request请求转发2. Response2. 1 Response设置响应数据功能介绍2. 2 Response完成重定向2. 3 Response响应字符数据2. 4 Response响应字节数据1. Request 1. 1Request继承体系 1.2 Request获取请求数据 1.3 …

制造企业如何借数字化能力进军万亿国际市场?

历时七十余载&#xff0c;中国建立了世界最完整的现代工业体系&#xff0c;实现了从“制造大国”向“制造强国”的历史性跨越&#xff0c;同时&#xff0c;这片土地也孕育了全球最庞大的自动化物流系统。 报告显示&#xff0c;从2012到2021年&#xff0c;中国社会物流总额和社…

转行软件测试我后悔了

很多时候&#xff0c;都在想当初做的转行软件测试行业的决定是对的吗&#xff1f;现在后悔还来得及吗&#xff1f; 记得在求职的时候&#xff0c;面试官经常问我&#xff1a;“为什么要选择软件测试工作?” 而我也会经常说一堆自己有的没的优势去应付。 工作这么久了&#x…

anaconda迁移深度学习虚拟环境 and 在云服务器上配置

1 anaconda 虚拟环境操作 1、 查看虚拟环境 conda info -e2、 创建新的虚拟环境 conda create -n deeplearning_all pip python3.63、 激活新建的虚拟环境 Conda activate deeplearning_all2 环境中相关库的版本即安装说明&#xff08;这些库都是对应匹配的&#xff09; …

【git】git@github.com: Permission denied (publickey).报错问题

1、引发这个问题的情况 本媛开发&#xff0c;会经常性用到gitee & GitHub两个库 毕竟国内项目转战仓到gitee&#xff0c; 但是国外原框架还是GitHub居多 于是就出现连接pull-push经常性切换问题 这个报错是因为本地两个仓都有ssh公共私有密钥导致的 2、解决方案&#xff…

ECharts数据可视化(案例)

ECharts数据可视化 ECharts介绍 官网链接&#xff1a;https://echarts.apache.org/zh/index.html ECharts是一个使用 JavaScript 实现的开源可视化库&#xff0c;可以流畅的运行在 PC 和移动设备上&#xff0c;兼容当前绝大部分浏览器&#xff08;IE8/9/10/11&#xff0c;Ch…

华为高级技术专家多年经验分享微服务治理体系、架构及实践文档

前言 都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升…

WEB前端网页设计 HTML网页代码 基础参数(一)

插入图片&#xff1a;<img src"./图像URL"> 整个HTML格式分为两大部分&#xff0c;一个是head部分&#xff0c;一个是body部分&#xff0c;其中head部分是用于书写网页样式&#xff0c;而body部分用于书写网页主题 标题标记 <h1></h1> ... <h6&…

生产型企业中采购管理系统的优势有哪些?

采购是生产型企业重要的环节&#xff0c;采购成本更是与企业利润息息相关。通常企业采购主要是取自于企业本身的需求&#xff0c;由于不同企业的需求不同&#xff0c;采购管理也就自然有所区别了。尤其是对于中小型企业而言&#xff0c;由于其本身规模有限&#xff0c; 生产资金…

[附源码]JAVA毕业设计健身房管理系统(系统+LW)

[附源码]JAVA毕业设计健身房管理系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&a…