leetcode面试经典150题——32 串联所有单词的子串(中等+困难)
题目: 串联所有单词的子串(1中等)
描述:
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = “cbaebabacd”, p = “abc”
输出: [0,6]
解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的异位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的异位词。
leetcode链接
方法一:滑动窗口
我们定义一个长度为p.size()大小的窗口,在s中不断移动此大小固定的窗口,并且比较窗口内的元素是否由p中的元素组成,考虑到题目给出的字符串都是由26个小写的字母组成因此,我们比较窗口内的元素,可以统计窗口内每个字母出现的次数,和p中每个字母出现的次数是否相同,如果相同,那么此窗口即为所求子串,因此我们定义两个大小为26的vector1和vector2,分别存储窗口中单词出现的次数和p中单词出现的次数。
时间复杂度:o(m+(n-m)*26) 需要o(m)来初始化vector存储单词的数量,后面有n-m个窗口,因此需要比较n-m次单词的数量,每次比较需要比较26个元素,因此时间复杂度为o((n-m)*26)
空间复杂度:o(1) 只需要常量级的空间
我们先统计第一个窗口的字母数量,再循环统计后面窗口的字母数量,如图所示,一边删除前一个单词(第一个指针),一边增加后一个窗口字母(后一个指针),即可得到当前指针内窗口字母的数量

vector<int> findAnagrams(string s, string p) {int n = s.size();int m = p.size();vector<int> ans;//s的大小小于p时候,肯定不存在满足条件子串if(n<m){return ans;}vector<int> sCount(26,0);vector<int> pCount(26,0);//先统计第一个窗口单词出现的次数for(int i=0;i<m;i++){sCount[s[i]-'a']++;pCount[p[i]-'a']++;}//比较第一个窗口是否为所求子串if(sCount==pCount){ans.push_back(0);}for(int i=0;i<n-m;i++){//统计下一个窗口的字母数量sCount[s[i]-'a']--;sCount[s[i+m]-'a']++;if(sCount==pCount){ans.push_back(i+1);}}return ans;
}
方法二:
考虑我们方法一花费的时间主要在滑动窗口每种字母数量与p的对比上,因此我们方法二不再统计每个窗口的字母数量,我们存储滑动窗口和p的每种单词的数量差值,并且用differ记录数量不一样的字母的个数,那么如果differ=0,表示所有字母的数量都相同,那么该窗口即为所求窗口,因此我们通过判断differ是否为0来判断是否为子串,省去了判断每一种字母数量的时间。
时间复杂度:o(m+n-m) o(m)用来初始化vector,后面有n-m个窗口需要比较,比较的时间复杂度为o(1)
空间复杂度:o(1) 申请了常量级的空间
vector<int> findAnagrams(string s, string p) {int n = s.size();int m = p.size();vector<int> ans;if(n<m){return ans;}vector<int> count(26,0);for(int i=0;i<m;i++){count[s[i]-'a']++;count[p[i]-'a']--;}int differ = 0;for(int i=0;i<26;i++){//统计第一个窗口不同数量字母的个数if(count[i]!=0){differ++;}}if(differ == 0){//如果没有则第一个窗口即为所求的子串ans.push_back(0);}for(int i=0;i<n-m;i++){if (count[s[i] - 'a'] == 1) { // 窗口中字母 s[i] 的数量与字符串 p 中的数量从不同变得相同--differ;} else if (count[s[i] - 'a'] == 0) { // 窗口中字母 s[i] 的数量与字符串 p 中的数量从相同变得不同++differ;}--count[s[i] - 'a'];if (count[s[i + m] - 'a'] == -1) { // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从不同变得相同--differ;} else if (count[s[i + m] - 'a'] == 0) { // 窗口中字母 s[i+pLen] 的数量与字符串 p 中的数量从相同变得不同++differ;}++count[s[i + m] - 'a'];if(differ==0){ans.push_back(i+1);}}return ans;
}
题目: 串联所有单词的子串(2困难)
描述:
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。 “acdbef” 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。
示例 1:
输入:s = “barfoothefoobarman”, words = [“foo”,“bar”]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 “barfoo” 开始位置是 0。它是 words 中以 [“bar”,“foo”] 顺序排列的连接。
子串 “foobar” 开始位置是 9。它是 words 中以 [“foo”,“bar”] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
leetcode链接
方法一:
类似于上题的方法二,我们用differ记录窗口单词出现次数和words中出现次数之差,如果differ为空,那么说明窗口中的单词和words中的单词相同。
定义n为words的大小,m为words中每个单词的长度,ls为s字符串的长度,那么每个窗口的长度应该为nm。首先我们需要将字符串s分成单词组,即分成一组有长度为m的单词组成的单词组,那么应该有m种分法,这里解释一下为什么是m种:假如字符串0123456按两个一分,那么有0 12 34 56和01 23 45 6这两种分法,如果按三个一分,那么有0 123 456和01 234 56和0123 456这三种分法,以此类推字符串按m个一分一共有m种分法,然后对于这里的每一种分法我们进行滑动窗口,来判断当前窗口是否为所求的子串,窗口一次移动一个单词的长度,即为移动m,那么即为左边减去一个单词,右边加上一个单词。
时间复杂度:o(lsm) 一共有m种分法,每一种分法我们都需要利用滑动窗口,而滑动窗口的时间复杂度为o(ls),所以总时间复杂度为o(lsm)
空间复杂度:o(nm) 一共m种分法,每一种都需要定义大小为n的unordered_map
vector<int> findSubstring(string s, vector<string>& words) {int n = words.size();int m = words[0].size();int ls = s.size();vector<int> ans;//枚举每一种单词组合的起始位置 for(int i=0;i<m&&i+n*m<=ls;i++){unordered_map<string,int> differ;for(int j = 0;j<n;j++){//统计窗口中单词出现的次数 differ[s.substr(i + j * m, m)]++;}for(int j=0;j<n;j++){//如果窗口中单词出现的次数和words中一样,那么在differ中删去 if(--differ[words[j]]==0){differ.erase(words[j]);}}//ls-m*n为剩余的字母数量,滑动窗口,每次移动一个单词的长度 for(int start=i;start<ls-m*n+1;start+=m){if(start!=i){//右边加入一个单词 string word = s.substr(start+(n-1)*m,m);if(++differ[word]==0){differ.erase(word);}//左边减去一个单词 word = s.substr(start-m,m);if(--differ[word]==0){differ.erase(word);}}//如果窗口中所有单词出现的次数和words一样则为所求子串 if(differ.empty()){ans.push_back(start);}}}return ans;
}
相关文章:
leetcode面试经典150题——32 串联所有单词的子串(中等+困难)
题目: 串联所有单词的子串(1中等) 描述: 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串(包括相同的字符串&…...
oracle关联更新
业务场景中需要对特定数据进行关联更新,记录一下关联更新语法: MERGE INTO fine_record_execute targ USING (SELECT "id","tname"FROM fine_record_executeWHERE "username" LIKE %目标人物%AND "time">20…...
SWT技巧
实现控件的刷新 问题可以简化如下,点击上方按钮,使下方按钮移动,但要求在监听事件里新建按钮对象,而不是使用原来的按钮(原来的按钮被移除了)。 解决代码如下: public class TestUI {protecte…...
3.数据结构
3.1 数据结构分类 常见的数据结构包括数组、链表、栈、队列、哈希表、树、堆、图,它们可以从“逻辑结构”和“物理结构”两个维度进行分类。 3.1.1逻辑结构:线性与非线性 逻辑结构揭示了数据元素之间的逻辑关系。在数组和链表中,数据按照…...
一篇文章完成Hbase入门
文章目录 一、简介1、数据模型结构2、物理存储结构3、数据模型4、基本架构 二、安装1、下载解压安装包2、修改配置文件3、启动服务(单机、集群)4、配置高可用(HA) 三、命令行操作1、建表2、新增/更新数据3、查看表数据4、删除数据5、修改默认保存的数据版本 四、架构1、RegionS…...
使用PotPlayer播放器查看软解和硬解4K高清视频时的CPU及GPU占用情况
目录 1、问题说明 2、PotPlayer播放器介绍 3、视频的软解与硬解 4、使用PotPlayer查看4K高清视频软解和硬解时的CPU占用情况 4.1、使用软解时CPU和GPU占用情况 4.2、使用硬解时CPU和GPU占用情况 5、最后 VC常用功能开发汇总(专栏文章列表,欢迎订阅…...
怎么做excel表格的二维码?文件快速做二维码的教程
Excel表格怎么做成二维码来扫码插看呢?Excel是工作中常用的一种文件格式,想要将表格内容分享给其他人查看,那么将表格生成二维码的方法会更加的方便快捷,其他人只需要扫描二维码就可以查看或者下载文件。表格excel二维码可以通过文…...
Clion取消double shift(按两下shift键)全局搜索
Clion 取消 double shift(按两下 shift 键)全局搜索。 如下图所示打开 setting。 点击 advanced setting,搜索 disable,取消勾选左侧复选框,点击 ok。...
Spring RabbitMQ那些事(2-两种方式实现延时消息订阅)
目录 一、序言二、死信交换机和消息TTL实现延迟消息1、死信队列介绍2、代码示例(1) 死信交换机配置(2) 消息生产者(3) 消息消费者 3、测试用例 三、延迟消息交换机实现延迟消息1、安装延时消息插件2、代码示例(1) 延时消息交换机配置(2) 消息生产者(3) 消息消费者 3、测试用例 …...
免费SSL证书有效期只有90天?太短?
随着网络安全问题日益受到重视,SSL证书成为了网站安全的必需品。然而,在许多情况下,免费提供的SSL证书往往只有90天的有效期,这种期限对于很多用户来说显得过于短暂。 首先,我们要理解为什么 SSL 证书的有效期设定为90…...
Java小游戏 王者荣耀
GameFrame类 所需图片: package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayLis…...
Python:diskcache实现基于文件的数据缓存
diskcache是一个基于Sqlite文件的数据缓存 文档 https://grantjenks.com/docs/diskcache/https://github.com/grantjenks/python-diskcachehttps://pypi.org/project/diskcache/ 示例 from diskcache import Cache# 指定文件夹 cache Cache(./cache)# 存 cache.set(name, …...
微信小程序 - 一篇带你解读小程序强制更新(冷/热启动)
在小程序开发中,我们会不可避免的涉及到小程序新版本迭代的问题,因为小程序的更新机制是异步的,新版本发布后并不会立刻应用到所有的现有用户,部分用户用的可能还是原来的旧版本,但如果是急需修复的 bug 或其他急需上线…...
关于接口测试自动化的总结与思考!
序 近期看到阿里云性能测试 PTS 接口测试开启免费公测,本着以和大家交流如何实现高效的接口测试为出发点,本文包含了我在接口测试领域的一些方法和心得,希望大家一起讨论和分享,内容包括但不仅限于: 服务端接口测试介…...
如何用低代码的思路设计文字描边渐变组件
前言 文字特效设计一直是困扰 Web 前端 Css 世界多年的问题, 比如如何用纯 Css 实现文字描边, 渐变, 阴影等, 由于受限于浏览器兼容性的问题, 我们不得不使用其他替代方案来实现. 平时工作中我们使用 PS 等设计工具能很容易的实现文字渐变等特效, 但是随着可视化技术的成熟, 我…...
Linux 网络通信
(一)套接字Socket概念 Socket 中文意思是“插座”,在 Linux 环境下,用于表示进程 x 间网络通信的特殊文件 类型。本质为内核借助缓冲区形成的伪文件。 既然是文件,那么理所当然的,我们可以使用文件描述符引用套接字。Linux 系统…...
借力互联网,民营医院探索互联网医疗服务的发展方向
民营医院互联网医疗服务是指利用互联网技术和平台,为患者提供更加便捷、高效的医疗服务。在当前数字化时代,互联网医疗服务正逐渐成为医疗行业的新趋势,也为民营医院开拓了更广阔的发展空间。下面将围绕这一主题进行讨论: 首先&a…...
office tool plus工具破解word、visio等软件步骤
第一步:下载工具 破解需要用到office tool plus软件 office tool plus软件下载地址:Office Tool Plus 官方网站 - 一键部署 Office 选择其中一个下载到本地(本人选择的是第一个的云图小镇下载方式) 第二步:启动工具 …...
python之pyqt专栏5-信号与槽1
在上一篇文章,我们了解到如果想要用代码改变QLabel的文本内容,可以调用QLabel类的text()函数。 但是现在有个这样的需求,界面中有一个Button与一个Label,当点击Button时,将Label的内容改变为“Hello world!…...
【JMeter】不同场景下的接口请求
场景1: 上传文件接口即Content-Type=multipart/form-data 步骤: 1. 接口url,method以及path正常填写 2.文件上传content-type是multipart/form-data,所以可以勾选【use multipart/form-data】,如果还有其他请求头信息可以添加一个请求头元件 3.请求参…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
