每天一道LeetCode-----给定字符串s和字符数组words,在s中找到words出现的位置,words内部字符串顺序无要求
Substring with Concatenation of All Words
原题链接Substring with Concatenation of All Words
题目意思是给定字符串s和字符数组words,在s中寻找words出现的位置,words内部的字符串顺序没有要求
此问题可以直接顺序搜索,假设s
的长度为m,words
的长度为n,words
中每个单词的长度为w,复杂度是O((m-n*w)*n)
,需要利用两个unordered_map<string,int>
,一个记录每个单词总共需要多少个,一个记录当前遍历到的单词数,如果遇到不在words
中的单词,就break
从下一个开始找
另一种方法是使用滑动窗口,也是利用两个unordered_map<string, int>
。原理是当不匹配是移动起始点,每一移动w个距离。不匹配有两种情况
- 当前单词不是words中的单词,重新开始找,初始化负责记录遍历到的单词数的那个map
- 当前单词word是words中的单词,但是这个单词已经够了,不再需要这个单词了。此时需要将窗口向右移动,直到出现第一个word为止,从这个word后面开始记录
举个例子,
s = "barfoobarfoothebar";
words = ["bar","bar","foo","the"];unordered_map<string, int> counts;
/** 记录每个单词需要的次数* bar foo the* 2 1 1*/unordered_map<string, int> seen;
/** 记录当前找到的单词数* bar foo the* 0 0 0*/int count;
/* 记录当前找到的单词数,0,目标大小为words的大小,4 */int startIndex;
/* 开始位置,0,找到就把它添加到结果的vector中 *//*1. 从s起点开始找,每3一判断,第一个bar,"bar"是要找的单词(在counts中),给seen对应为加一,此时seen["bar"]=1, count=1;2. 接着找第二个单词"foo",也在counts中,给seen对应位加一,此时seen["foo"]=1, count=2;3. 继续找"bar",也在counts中,给seen加一,此时seen["bar"]=2,count=3;4. 继续找"foo",也在counts中,给seen加一,此时seen["foo"]=2,但是counts["foo"]=1,表示"foo"只需要一个,此时不满足条件,移动1. 从startIndex开始删除单词,直到找到第一个"foo"2. 删掉"bar",此时seen["bar"]=1,count=1,startIndex=0+3=3;3. 删掉"foo",此时seen["foo"]=1,不改变count,因为当不满足时,没有增加count,startIndex=6;4. 找到第一个"foo"了,继续查找单词5. 继续找"the",在counts中,给seen加一,此时seen["the"]=1,count=26. ...7. 最终找到count==n,将startIndex=6添加到结果中8. 再右移一个单词,删掉"bar",此时seen["bar"]=1,count=3,startIndex=99. 继续寻找10. ...11. 遇到单词"abc",不在counts中,重置seen,count,startIndex12. 继续寻找13. ...14. 结束*/
代码如下
class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> res;if(s.size() == 0 || words.size() == 0)return res;unordered_map<string, int> dict;for(auto &str : words)++dict[str];int n = s.size();int cnt = words.size();int wl = words[0].size();/* * 每个单词长度为wl,那么只需要循环wl次,每次移动wl个为* 0, wl, 2*wl, 3*wl ...* 1, 1+wl, 1+2*wl, 1+3*wl...* 2, 2+wl, 2+2*wl, 2+3*wl...* ...*/for(int i = 0; i < wl; ++i){int left = i;int count = 0;unordered_map<string, int> tdict; //seen/* 每次移动wl个 */for(int j = i; j <= n - wl; j+=wl){string str = s.substr(j, wl);/* 如果是需要的单词,就添加到seen中 */if(dict.count(str)){tdict[str]++;/* 如果已经不需要了,就不用增加count */if (tdict[str] <= dict[str]) count++;else{/* 如果当前这个单词是多余的,超出了数量限制,就移动窗口 */while (tdict[str] > dict[str]) {string str1 = s.substr(left, wl);tdict[str1]--;/* 因为多余的那个单词没有增加count,所以也不需要减count */if (tdict[str1] < dict[str1]) count--;left += wl;}}/* 如果到所有,右移 */if (count == cnt) {res.push_back(left);// advance one wordtdict[s.substr(left, wl)]--;count--;left += wl;}}/* 不是需要的单词,重置所有 */else{tdict.clear();count = 0;left = j + wl;}}}return res;}
};
啊啊啊啊下午的心情一点也不好-.-
每天一道LeetCode-----给定字符串s和字符数组words,在s中找到words出现的位置,words内部字符串顺序无要求相关推荐
- 字符串转换成字符数组的一些方法
内容基本源自某公众号,在其基础上进行了部分补充 字符串转为字符数组的一些方法 1. split() 2. 扩展运算符 3. 字符串的解构赋值 4. Array.from 1. split() spli ...
- LeetCode/LintCode 题解丨一周爆刷字符串:旋转字符数组
描述 给定一个字符数组 s 和一个偏移量,根据偏移量原地旋转字符数组(从左向右旋转). offset >= 0 s 的长度 >= 0 原地旋转意味着需要在函数中更改字符数组 s.你不需要返 ...
- 在Python中将字符串拆分为字符数组
Given a string and we have to split into array of characters in Python. 给定一个字符串,我们必须在Python中拆分为字符数组. ...
- 外挂学习之路(12)--- 用CE搜索字符串和搜索字符数组的区别
用VS2008写个小工程做测试,得到如下一些结论 代码如下: TCHAR test[50] = TEXT("你好啊"); void CasciiDlg::OnBnClickedBu ...
- 嵌入式linux编程过成中模块从串口读数需要特定的字符段并且需要每两位字符数组元素转换成一个16进制数(提取特定字符串+字符串转16进制)
嵌入式linux编程过成中用到zigbee模块 zigbee从串口读数需要特定的字符段并且需要每两位字符数组元素转换成一个16进制数 (提取特定字符串+字符串转16进制) #include<st ...
- asp.net(c#)字符串转换成字符数组 字符串转换成int 数组
问题: 一个字符串是string a="a,b,c,d" ,另一个是string b="1,2,3,4" ,第一个转换成string[]类型的,第二个转 ...
- C语言补漏:字符串指针与字符数组传参
字符串指针与字符数组传参 深信服的笔试上被吊打,其中对一道用指针做形参的题目印象十分深刻,借此恶补了一晚上指针,今天总结,以作警示. 试想有如下情形,将一个字符串指针做形参赋值函数修改其字符串,函 ...
- 字符串,字符指针,字符串指针,字符数组
对于指针可能是大多数程序员最痛苦的事,尤其是指针和字符串和数组三者放在一起的时候,经历了几次错误后,我打算总结一下这几者的区别. 字符串:"asdasfsff",c语言中后面有'\0'. 字符数组:A ...
- java怎么把字符串转换成字符数组
此博客用于个人编程学习记录. 文章内容来自于: java怎么把字符串转换成字符数组-Java基础-PHP中文网https://www.php.cn/java/base/435415.html java ...
最新文章
- MSLicensing​中断远程桌面连接
- 腾讯天津数据中心余热回收应用初探
- 研发协同平台持续交付2.0架构演进
- spark内存溢出怎么解决_和平精英:更新需要预留6G内存,玩家抱怨手机扛不住,怎么解决?...
- Servlet的单例模式
- PCL使用类成员函数作为pclvisualizer的回调函数
- 2022年Java 工程师面试题
- 【前端实用工具集】js对url进行编码和解码的三种方式
- 计算机网络重置点命令,重置网络命令 重装系统如何重置网络命令
- CST微波工作室学习笔记—14.天线设计实例
- 使用Pano2VR实现客厅VR效果
- 突发!图森未来CEO侯晓迪被罢免,公司疑遭SEC、FBI联手调查,市值一夜砍半
- 十六进制转换成八进制(超级详细注释了)
- 学计算机的人会单身吗,大学哪些专业最容易单身 大学哪些专业最不容易脱单...
- 计算机音乐谱软件假装,愚人节整人方法 让电脑遭殃的整蛊软件
- Win95+VC6+IE4+MSXML3时的XMLHTTP解决方法
- oSIP协议栈(及eXoSIP,Ortp等)使用入门
- word2010排版技巧
- 抖音Dou+到底该怎么投放?dou+投放的最佳时间:国仁网络资讯
- 如何去除discuz X2论坛网址中的forum.php
热门文章
- C语言学习之求S=a+aa+aaa+... +aa.....aa之值,其中a是一个数字,n表示a的位数.
- 数据结构课程设计---学生信息管理系统
- 数据结构课程设计----基数排序
- 剑指offer-跳台阶
- RxJava尝试取代Handler初探
- 维护索引——通过重组索引提高性能
- Spring(二)IOC底层实现原理
- git学习之时光机穿梭(四)
- 远程服务器存储之JDK方式
- FreeMarker教程