Leetcode——30.与所有单词相关联的字串【##】
@author: ZZQ
@software: PyCharm
@file: leetcode30_findSubstring.py
@time: 2018/11/20 19:14
题目要求:
给定一个字符串 s 和一些长度相同的单词 words。在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出: [0,9]
解释: 从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:
s = "wordgoodstudentgoodword",
words = ["word","student"]
输出: []
这个案例有点迷,题目明明说words里面的单词都是等长的。。。
思路:
方法一:
拿到题目,我们需要做的是找出匹配words中所有单词的子串的下标。
首先,我们用一个hashmap_m1去记录words中出现的单词及其个数,
然后,开始遍历,依次比较从i,i+words_len的所有子串是否匹配words里单词的某种自由组合,当i的值>s_len-words_num*word_len时,剩余的子串也不够匹配的,i至此停止遍历。
在内层循环中, 我们设置一个新的hashmap_m2来存储当前子串中匹配到的单词及其个数。
当该单词不在hashmap_m1中时,匹配失败,break
当hashmap_m2中该单词的个数超出hashmap_m1中该单词的个数时,匹配失败,break
当j刚好等于words_nums时,说明匹配成功,则将当前的下标i存入ans中。
AC代码如下:
class Solution(object):
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
if s == "" or words == []:
return []
ans = []
hash_m1 = {}
words_num = len(words)
word_len = len(words[0])
s_len = len(s)
if s_len < words_num:
return []
for word in words: # 记录每个单词出现的次数
if word not in hash_m1:
hash_m1[word] = 1
else:
hash_m1[word] += 1
for i in range(s_len-words_num*word_len+1):
hash_m2 = {}
j = 0
while j < words_num: # 需要匹配的单词的个数
current_word = s[i+j*word_len:i+(j+1)*word_len]
if current_word in hash_m1:
if current_word not in hash_m2:
hash_m2[current_word] = 1
else:
hash_m2[current_word] += 1
if hash_m2[current_word] > hash_m1[current_word]:
break
else:
break
j += 1
if j == words_num:
ans.append(i)
return ans
方法二:
但是这种方法比较慢,看了网上大神的解法,于是有了方法二。
这是一个可以达到O(n)的方法。i不是一个字母一个字母的遍历,而是一个单词一个单词的遍历。
比如说:
当前words中所有单词的长度都为3,则遍历的方法是先遍历0,3,6,9,12...,然后扫描1,4,7,10,13,...,再扫描2,5,8,11,14,...,也就是说外层循环i只需要遍历【0,3】即可。
我们先设置一个hashmap_m1用于保存words中每个单词出现的个数,然后,对于某个i,设置left来记录某个字串的起始下标,设置count来记录匹配成功的单词个数,设置临时变量k遍历【i,len(s)】之后的所有字母,但此时不依次遍历,而是一个单词一个单词的遍历。设置临时字典hashmap_m2来存储在当下循环中匹配到的单词及其个数。
内层循环中,判断当前的current_word是否在hashmap_m1:
如果在,则将hashmap_m2中该单词的个数加1,同时判断hashmap_m2中current_word的个数是否超过hashmap_m1中current_word,如果没有超,则将count加1,否则,说明此时匹配到的单词个数不符合words里的单词个数,则从hashmap_m2中去掉最前面的一个单词,然后将count减1,同时将left后移word_len个单位,直至hashmap_m2【current_word】<=hashmap_m1【current_word】。 当count的值与words中单词的个数相同时,说明匹配成功,则将该起始下标left添加到ans中,然后将left后移word_len个单位,同时将count减1。
如果current_word不在hashmap_m1则,则说明之前的所有匹配都失败,此时应该将hashmap_m2清零,同时将left后移到j+word_len的位置(重新开始匹配)。
AC代码如下:
class Solution(object):
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
if s == "" or words == []:
return []
ans = []
hash_m1 = {}
words_num = len(words)
s_len = len(s)
if s_len < words_num:
return []
for word in words:
if word not in hash_m1:
hash_m1[word] = 1
else:
hash_m1[word] += 1
word_len = len(words[0])
for i in range(word_len):
left = i # 记录起始下标
count = 0 #记录匹配成功的个数
hash_m2 = {} # 记录匹配到的单词及其个数
j = i # 从i开始往后遍历
while j <= s_len - word_len: # 循环停止条件是遍历到最后一个单词所在位置
current_word = copy.deepcopy(s[j:j + word_len]) # 当前单词
if current_word in hash_m1: # 如果单词在hash_m1 中
if current_word not in hash_m2: # 将其加入hash_m2
hash_m2[current_word] = 1
else:
hash_m2[current_word] += 1
if hash_m2[current_word] <= hash_m1[current_word]: # 如果该单词在hash_m2中的个数小于等于其在hash_m1中的个数,将count+1
count += 1
else: # 否则将hash_m2中最先匹配到的单词剔除,直至hash_m2[current_word] <= hash_m1[current_word]
while hash_m2[current_word] > hash_m1[current_word]:
temp_word = s[left:left+word_len]
hash_m2[temp_word] -= 1
if hash_m2[temp_word] < hash_m1[temp_word]:
count -= 1
left += word_len
if count == words_num: # 匹配成功
if left not in ans:
ans.append(left)
hash_m2[s[left:left + word_len]] -= 1 # left后移一个单词的长度,hash_m2中最先匹配到的单词移除一个
count -= 1
left += word_len
else: # 当前单词不在hash_m1中,匹配失败,重新开始匹配,count清零,left设置到当前位置
hash_m2.clear()
count = 0
left = j + word_len
j += word_len
return ans
Leetcode——30.与所有单词相关联的字串【##】的更多相关文章
- [leetcode] 30. 与所有单词相关联的字串(cn第653位做出此题的人~)
30. 与所有单词相关联的字串 这个题做了大概两个小时左右把...严重怀疑leetcode的judge机器有问题.同样的代码交出来不同的运行时长,能不能A题还得看运气? 大致思路是,给words生成一 ...
- 30. 与所有单词相关联的字串、java实现
题目描述: 给定一个字符串 s 和一些长度相同的单词 words.在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置. 注意子串要与 words 中的单词完全匹配,中间不能有其他字符, ...
- Leetcode 30.与所有单词相关联的子串
与所有单词相关联的字串 给定一个字符串 s 和一些长度相同的单词 words.在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置. 注意子串要与 words 中的单词完全匹配,中间不能 ...
- LeetCode(30):与所有单词相关联的字串
Hard! 题目描述: 给定一个字符串 s 和一些长度相同的单词 words.在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置. 注意子串要与 words 中的单词完全匹配,中间不能 ...
- [Swift]LeetCode30. 与所有单词相关联的字串 | Substring with Concatenation of All Words
You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...
- 030 Substring with Concatenation of All Words 与所有单词相关联的字串
给定一个字符串 s 和一些长度相同的单词 words,找出 s 与 words 中所有单词(words 每个单词只出现一次)串联一起(words中组成串联串的单词的顺序随意)的字符串匹配的所有起始索引 ...
- Java实现 LeetCode 30 串联所有单词的子串
30. 串联所有单词的子串 给定一个字符串 s 和一些长度相同的单词 words.找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置. 注意子串要与 words 中的单词完全匹配, ...
- [LeetCode] 30. 串联所有单词的子串
题目链接: https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/ 题目描述: 给定一个字符串 s 和一 ...
- Leetcode 30 串联所有单词的子串 滑动窗口+map
见注释.滑动窗口还是好用. class Solution { public: vector<int> findSubstring(string s, vector<string> ...
随机推荐
- 关于react的一点工作总结
首先,react是Facebook开发的一套前端框架,仅仅是MVC中的V.核心思想是“封装组件”,组件封装后可以作为一个独立的实体被引入到新的组件中,这样新的组件就又是一个实体了,由于组件的实现了可复 ...
- 使用vs2010编译lua5.1源代码生成lua.lib
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/wangbin_jxust/article/details/37557807 一.打开vs2010 二 ...
- Scala学习之路 (六)Scala的类、对象、继承、特质
一.类 1.类的定义 scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用 ...
- Linux下RPM包的安装
Linux下RPM包安装 二进制包(RPM包.系统默认包) RPM安装 rpm -ivh 包全名(查询依赖网址:http://www.rpmfind.net) -i(install):安装 -v(ve ...
- 无法找到“XXX.exe”的调试信息,或者调试信息不匹配。未使用调试信息生成二进制文件
1.问题症状 已经处于Debug模式,运行时完全正常,但是一调试就出现对话框,显示出错信息:“无法找到“XXX.exe”的调试信息,或者调试信息不匹配.未使用调试信息生成二进制文件.” 2.解决方法 ...
- OpenCV——Harris、Shi Tomas、自定义、亚像素角点检测
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- CentOS中安装Azkaban 2.5
必备软件 yum install git -y 单机安装步骤 git clone https://github.com/azkaban/azkaban.git cd azkaban; ./gradle ...
- QT的常用对话框的应用
QMessageBox类提供了常用的弹出式对话框:提示.警告.错误.询问.关于对话框 需要添加头文件 #include <QMessageBox> MESSAGE 是要是显示的字符串 v ...
- WebView之禁止调用第三方浏览器
一.WebView官方简洁: 一个显示视图的web页面.在这个类的基础上你可以滚自己的web浏览器或简单地显示一些网上的内容.它使用WebKit渲染引擎显示web页面,包括方法向前和向后导航历史,放大 ...
- struts2_文件上传的功能
使用Struts内置的fileUpload拦截器(已默认配置)即可,设计的电商网站,提供用户头像上传的功能 1. 2. 3. 4. 5. 5.未使用拦截器 6.未使用filename 7. 8. 9.