子序列 392、524、521、522

392. 判断子序列(简单)

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

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

进阶:

如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

致谢:

特别感谢 @pbrother 添加此问题并且创建所有测试用例。

示例 1:

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

示例 2:

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

提示:

  • 0 <= s.length <= 100
  • 0 <= t.length <= 10^4
  • 两个字符串都只由小写字符组成。

解法一、双指针遍历 

等于一个挪一下。如果s真的是很多个字符串,只需要引出一个数组,来当作指针,时间复杂度依旧是O(n)(t的长度)。

class Solution {public static boolean isSubsequence(String s, String t) {int p = 0;int lenS = s.length(),lenT = t.length();if(lenS > lenT||lenS == 0)return false;for(int i = 0;i< lenT;i++){if(t.charAt(i) == s.charAt(p)){p++;}}if(p == lenS)return true;return false;}
}

解法二、动态规划

顺便提前去学了一下动态规划~归纳核心:先求子问题,根据子问题求父问题。保存子问题答案,避免重复运算。

算法-动态规划 Dynamic Programming--从菜鸟到老鸟-CSDN博客

 对于f[i][j],表示t中从i开始,j字符第一次出现的位置。大循环表从后往前遍历,小循环表26个字母遍历,在小循环中,如果位置i是字母j,那么f[i][j]=i,表明i处出现了。否则,是f[i+1][j],相当于绵延、查表求解,子问题和父问题答案相等。(例如"abcd",查c之后c的位置,就是2。查b之后c的位置,就是b+1=c那里存的。查a之后c的位置,就是a+1=b(这里已经放进c的答案了)处存的)至于一开始的f[m][i],可以让m进行转移,代表之后不再存在这个字母。

预处理后,开始考虑n。对于s字符串"abcd",f[0][a]代表0开始后’a‘的位置,如果是m,转移。如果不是,add跳到a的下个位置。+1是因为这个位置已经考虑过了,就是a。

add代表坐标。f之所以有m+1的长度,是为了在m处存下m,也就是维续状态转移。

class Solution {public boolean isSubsequence(String s, String t) {int n = s.length(), m = t.length();int[][] f = new int[m + 1][26];for (int i = 0; i < 26; i++) {f[m][i] = m;}for (int i = m - 1; i >= 0; i--) {for (int j = 0; j < 26; j++) {if (t.charAt(i) == j + 'a')f[i][j] = i;elsef[i][j] = f[i + 1][j];}}int add = 0;for (int i = 0; i < n; i++) {if (f[add][s.charAt(i) - 'a'] == m) {return false;}add = f[add][s.charAt(i) - 'a'] + 1;}return true;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/is-subsequence/solutions/346539/pan-duan-zi-xu-lie-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 
524. 通过删除字母匹配到字典里最长单词(中等)

给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。

如果答案不止一个,返回长度最长且字母序最小的字符串。如果答案不存在,则返回空字符串。

示例 1:

输入:s = "abpcplea", dictionary = ["ale","apple","monkey","plea"]
输出:"apple"

示例 2:

输入:s = "abpcplea", dictionary = ["a","b","c"]
输出:"a"

提示:

  • 1 <= s.length <= 1000
  • 1 <= dictionary.length <= 1000
  • 1 <= dictionary[i].length <= 1000
  • s 和 dictionary[i] 仅由小写英文字母组成

解法一、动态规划

上道题学了所以这道题用一下。注意:两个传入参数,这道题和上道题基本算是反的

道理上和上道题差不多~字典序部分讨论,如果len大于最大值,则直接更新;如果等于,那么使用compareTo,返回的是负数则字典序小于,更新。

 public static String findLongestWord(String s, List<String> dictionary) {int lenS = s.length();int[][] f = new int[lenS+1][26];for(int i = 0;i < 26;i++){f[lenS][i] = lenS;}for(int i = lenS - 1;i >= 0;i--){for(int j = 0;j < 26;j++){if(s.charAt(i) == j + 'a'){f[i][j] = i;}else{f[i][j] = f[i+1][j];}}}int maxLen = 0;int index = -1;for(int i = 0;i < dictionary.size();i++){String t = dictionary.get(i);int add = 0;boolean e = true;for(int j = 0;j < t.length();j++){if(f[add][t.charAt(j)-'a'] == lenS){e = false;break;}add = f[add][t.charAt(j)-'a']+1;}if(e && maxLen < t.length()){maxLen = t.length();index = i;}else if(e && maxLen == t.length()){if(dictionary.get(i).compareTo(dictionary.get(index))<0){index = i;}}}if(index == -1)return "";return dictionary.get(index);}

 

 解法二、双指针

同题一解法。这个if判断字典序和长度的方式,比我简明很多(直接记字符串就好)

class Solution {public String findLongestWord(String s, List<String> dictionary) {String res = "";for (String t : dictionary) {int i = 0, j = 0;while (i < t.length() && j < s.length()) {if (t.charAt(i) == s.charAt(j)) {++i;}++j;}if (i == t.length()) {if (t.length() > res.length() || (t.length() == res.length() && t.compareTo(res) < 0)) {res = t;}}}return res;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/longest-word-in-dictionary-through-deleting/solutions/996014/tong-guo-shan-chu-zi-mu-pi-pei-dao-zi-di-at66/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解法三、先排序再判断

长的和字典序小的放前面,之后直接遍历返回第一个就好啦。感觉这个写比较器的方法没学过,我学一下···开销肯定更大,因为不符合的部分也排序了

class Solution {public String findLongestWord(String s, List<String> dictionary) {Collections.sort(dictionary, new Comparator<String>() {public int compare(String word1, String word2) {if (word1.length() != word2.length()) {return word2.length() - word1.length();} else {return word1.compareTo(word2);}}});for (String t : dictionary) {int i = 0, j = 0;while (i < t.length() && j < s.length()) {if (t.charAt(i) == s.charAt(j)) {++i;}++j;}if (i == t.length()) {return t;}}return "";}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/longest-word-in-dictionary-through-deleting/solutions/996014/tong-guo-shan-chu-zi-mu-pi-pei-dao-zi-di-at66/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

521. 最长特殊序列 Ⅰ(简单)

给你两个字符串 a 和 b,请返回 这两个字符串中 最长的特殊序列  的长度。如果不存在,则返回 -1 。

「最长特殊序列」 定义如下:该序列为 某字符串独有的最长

子序列

(即不能是其他字符串的子序列) 。

字符串 s 的子序列是在从 s 中删除任意数量的字符后可以获得的字符串。

  • 例如,"abc" 是 "aebdc" 的子序列,因为删除 "aebdc" 中斜体加粗的字符可以得到 "abc" 。 "aebdc" 的子序列还包括 "aebdc" 、 "aeb" 和 "" (空字符串)。

示例 1:

输入: a = "aba", b = "cdc"
输出: 3
解释: 最长特殊序列可为 "aba" (或 "cdc"),两者均为自身的子序列且不是对方的子序列。

示例 2:

输入:a = "aaa", b = "bbb"
输出:3
解释: 最长特殊序列是 "aaa" 和 "bbb" 。

示例 3:

输入:a = "aaa", b = "aaa"
输出:-1
解释: 字符串 a 的每个子序列也是字符串 b 的每个子序列。同样,字符串 b 的每个子序列也是字符串 a 的子序列。

解法一、脑筋急转弯简化

一个字符串最长的特殊子序列当然是它自己,如果父序列都不是特殊的,那子序列也一定不是。

class Solution {public int findLUSlength(String a, String b) {int lenA = a.length();int lenB = b.length();if(lenA > lenB){return lenA;}else if(lenA < lenB){return lenB;}else{if(!a.equals(b))return lenA;}return -1;}
}

或者(原来这里可以用三目,学到了)

class Solution {public int findLUSlength(String a, String b) {return !a.equals(b) ? Math.max(a.length(), b.length()) : -1;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/longest-uncommon-subsequence-i/solutions/1306210/zui-chang-te-shu-xu-lie-i-by-leetcode-so-v9sr/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

522. 最长特殊序列 II(中等)

给定字符串列表 strs ,返回其中 最长的特殊序列 的长度。如果最长特殊序列不存在,返回 -1 。

特殊序列 定义如下:该序列为某字符串 独有的子序列(即不能是其他字符串的子序列)

 s 的 子序列可以通过删去字符串 s 中的某些字符实现。

  • 例如,"abc" 是 "aebdc" 的子序列,因为您可以删除"aebdc"中的下划线字符来得到 "abc" 。"aebdc"的子序列还包括"aebdc"、 "aeb" 和 "" (空字符串)。

 

示例 1:

输入: strs = ["aba","cdc","eae"]
输出: 3

示例 2:

输入: strs = ["aaa","aaa","aa"]
输出: -1

 

提示:

  • 2 <= strs.length <= 50
  • 1 <= strs[i].length <= 10
  • strs[i] 只包含小写英文字母

解法一、双指针遍历 

双指针即判断一个字符串是否是另一个字符串的子序列的方式。根据521题的讨论可得,子序列是,父序列未必是;父序列是,子序列一定是。也就是说,写成逻辑语言,父序列是=>子序列是

基本逻辑:如果一个字符串不是剩余所有字符串的子序列,那么把它的长度纳入考虑。

但这道题最致命的点,其实在考虑了521之后,会下意识认为它也有方式简化。。。起初用了排序的思想,按照字典序排,从长往短遍历。对于同一长度的字符串组,如果一个字符串不与任何字符串相等,那么它就是答案。该方式简短了isSubseq。

但是太复杂了。。比如:不能圈定固定长度。

class Solution {public int findLUSlength(String[] strs) {int n = strs.length;int ans = -1;for (int i = 0; i < n; ++i) {boolean check = true;for (int j = 0; j < n; ++j) {if (i != j && isSubseq(strs[i], strs[j])) {check = false;break;}}if (check) {ans = Math.max(ans, strs[i].length());}}return ans;}public boolean isSubseq(String s, String t) {int ptS = 0, ptT = 0;while (ptS < s.length() && ptT < t.length()) {if (s.charAt(ptS) == t.charAt(ptT)) {++ptS;}++ptT;}return ptS == s.length();}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/longest-uncommon-subsequence-ii/solutions/1623415/zui-chang-te-shu-xu-lie-ii-by-leetcode-s-bo2e/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解法二 参照521的长度简化(失败)

想的是排序然后同长度圈层遍历判断,事实证明根本不可能,因为短的字符串也可以是长的字符串的子序列

但写了很久,所以还是放一下

class Solution {public static int findLUSlength(String[] strs) {Arrays.sort(strs, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return Integer.compare(s1.length(), s2.length());}});int len = strs.length;int ans = -1;int p = len - 2,q = len - 1;while(p >= 0){while(p > 0 && strs[p].length() == strs[q].length()){p--;}if(strs[p].length()!= strs[q].length())p++;boolean check = true;for(int j = p;j < q;j++){for(int h = p;h<q;h++){if(j != h && strs[j].equals(strs[h])){check = false;break;}}if(check)ans = Math.max(ans,strs[j].length());}if(ans != -1)return ans;p = p-2;q = p+1;}if(strs[0].length() != strs[1].length())return strs[0].length();return -1;}
}

碎碎念

  • 学习了动态规划的基本思想
  • 522里学习了先看、衡量可行性 再动手写的想法,被521误导了
  • 学会了比较器的写法(
  • 熟悉了Arrays.sort 
  • 在524里,发现matches比equals慢很多,后续去搜了。前者是返回是否匹配正则,后者则是两个字符串是否相等,底层逻辑不一样
  • 其实还有List 可以用foreach语法但String不可以。。不过感觉太基础了

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

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

相关文章

C语言程序设计(二)

四.找素数 素数&#xff1a;除了1和它本身不再有其他因数的自然数。换句话说&#xff1a;一个大于1的自然数 &#xff0c;如果只能被1和它本身整除&#xff0c;那就是素数&#xff08;质数&#xff09;。 在打印中遇到的问题就是&#xff0c;知道怎么写却总是运行不起来。主要…

尚硅谷vue全家桶(vue2+vue3)笔记

Vue2 一、Vue核心 01_简介 1.特点 采用组件化模式&#xff0c;提高代码复用率、且让代码更好维护。声明式编码&#xff0c;让编程人员无需直接操作DOM&#xff08;命令式编码&#xff09;&#xff0c;提高开发效率。使用虚拟DOM优秀的Diff算法&#xff0c;尽量复用DOM节点。…

ks滑块验证码逆向分析与python识别

文章目录 1. 写在前面3. 接口分析3. 算法实现 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…

从零搭建pytorch模型教程(八)实践部分(二)目标检测数据集格式转换

前言 图像目标检测领域有一个非常著名的数据集叫做COCO&#xff0c;基本上现在在目标检测领域发论文&#xff0c;COCO是不可能绕过的Benchmark。因此许多的开源目标检测算法框架都会支持解析COCO数据集格式。通过将其他数据集格式转换成COCO格式可以无痛的使用这些开源框架来训…

在MATLAB中使用importrobot导入机械臂刚体树时没有找到模型文件,只显示坐标;改为使用loadrobot

没有mesh文件夹&#xff0c;所以找不到模型文件 改为使用loadrobot,直接加载刚体树数据

【C++题解】1782. 字符图形2-星号倒直角

问题&#xff1a;1782. 字符图形2-星号倒直角 类型&#xff1a;嵌套循环、图形输出 题目描述&#xff1a; 打印字符图形。 输入&#xff1a; 一个整数&#xff08; 0<n<10 &#xff09;。 输出&#xff1a; 一个字符图形。 样例&#xff1a; 输入&#xff1a; 3…

重生之我当程序猿外包

第一章 个人介绍与收入历程 我出生于1999年&#xff0c;在大四下学期进入了一家互联网公司实习。当时的实习工资是3500元&#xff0c;公司还提供住宿。作为一名实习生&#xff0c;这个工资足够支付生活开销&#xff0c;每个月还能给父母转1000元&#xff0c;自己留2500元用来吃…

深入探讨 I/O 多路复用:提升系统 I/O 效率的关键技术

摘要 I/O&#xff08;输入/输出&#xff09;操作是计算机系统中不可或缺的一部分&#xff0c;而 I/O 多路复用技术则是提高系统 I/O 效率的重要手段。本文将浅谈 I/O 的基本概念&#xff0c;重点探讨 I/O 多路复用技术的原理、优势以及在现代系统中的应用。 引言 在现代计算…

LoRaWAN设备的两种入网方式(ABP和OTAA)

目录 一、OTAA 1、名词解释 2、入网流程 二、ABP 三、两种入网方式的比较 一、OTAA 1、名词解释 &#xff08;1&#xff09;AppEUI&#xff1a;64位&#xff08;8字节&#xff09;的唯一标识符&#xff0c;用于标识特定的应用程序或组织&#xff08;如果用的是chirpstac…

Android BLE蓝牙广播发送数据

1. 调试BLE蓝牙广播数据 参考 android蓝牙BLE&#xff08;四&#xff09; —— 实战 android蓝牙BLE&#xff08;四&#xff09; —— 实战 - 简书 2. Android机可直接安装调试助手 BLE调试助手下载2024安卓手机版_手机app免费下载

【linux】在多核CPU下,好像看到不同进程在不同CPU调度

在2353这行打印的情况来看&#xff0c;操作系统好像给不同的进程分配不同的CPU&#xff0c;从上图来看&#xff0c;同一个进程好像基本使用的相同的CPU&#xff1a; 其实摸索syscall文件系统操作&#xff0c;本意是想找到内核文件系统中文件的创建&#xff0c;写入&#xff0c;…

Windosw下Visual Studio2022编译FFmpeg(支持x264、x265、fdk-acc)

FFmpeg 7.0 版本移除了 6.0 之前已弃用的 API&#xff0c;无法向下兼容。所以编译的版本选择FFmpeg 6.1.1。 一、安装Visual Studio2022 可参考另外一篇文章&#xff1a;Windows安装Visual Studio2022 QT5.15开发环境_qt5.15.2 vs2022-CSDN博客 二、安装MSYS2 下载地址&…

宝塔Docker部署Nuxt3 BBS项目

体验地址 BBS&#xff1a;http://bbs.sourcebyte.vip Nuxt3&#xff1a;https://nuxt.com.cn BBS项目介绍 BBS是开源字节最新研发的社区项目&#xff0c;包含产品中心&#xff0c;需求墙&#xff0c;工具&#xff0c;资讯4大板块。 1、产品中心&#xff1a;开源字节有众多…

Kafka知识总结(分区机制+压缩机制+拦截器+副本机制)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 分区机制 分区策略 分区策略是决定生产者将消息发送到哪个分区的…

MySQL 存储

关系型数据库是基于关系模型的数据库&#xff0c; 而关系模型是通过二维表来保存的&#xff0c;所以关系型数据库中的数据的村方式就是行列组成的表&#xff0c;每一列代表一个字段&#xff0c;每一行代表一条记录。表可以看作某个实体的集合&#xff0c;实体之间存在的联系需要…

【区块链】如何发行自己的加密货币到以太坊测试网络,remixIDE发行自己的数字货币

如何发行自己的加密货币到以太坊测试网络 环境 reminx在线编辑器&#xff1a;https://remix.ethereum.org/安装有小狐狸钱包插件&#xff08;MetaMask&#xff09; 如何部署代币&#xff1f; 创建一个名字叫做HelloMyToken.sol的文件。编写好智能合约&#xff0c;这边我要发…

bug+测试用例

bug的概念&#xff1a; 1.当且仅当规格说明是存在的并且正确&#xff0c;程序与规格说明之间的不匹配才是错误。 2.当需求规格说明书没有提到的功能&#xff0c;判断标准以最终用户为准&#xff1b;当程序没有实现其最终用户合理预期的功能要求时&#xff0c;就是软件错误 bug…

大模型算法面试题(十三)

本系列收纳各种大模型面试题及答案。 1、领域模型词表扩增是不是有必要的? 领域模型词表扩增是否必要&#xff0c;取决于多个因素&#xff0c;主要包括以下几个方面&#xff1a; 领域复杂性&#xff1a;如果领域本身非常复杂&#xff0c;包含大量专业术语、缩写、行业特定表达…

mybatis插入mysql数据:中文乱码

1.问题描述 中文字段乱码&#xff0c;不能正常显示 2.解决方法 猜测是未指定编码造成的&#xff0c;在配置文件mybatis-config.xml添加配置。 <environment id"development"><transactionManager type"JDBC"/><dataSource type"POO…

golang设置远程调试

1. 目标机器构建安装dlv https://github.com/go-delve/delve go build之后将编译号的dlv命令路径添加到PATH里 2. 目标机器下载源代码并且运行dlv dlv debug --headless --listen:2345 --api-version2 --accept-multiclient 3.本机添加go remote 4. 设置断点即可