题目链接: https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/

题目描述:

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例:

示例 1:

输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。

示例 2:

输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]

思路:

一开始,我的想法是,每次从s截取一定长度(固定的)的字符串,看这段字符串出现单词个数是否和要匹配的单词个数相等!如下代码:

class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
from collections import Counter
if not s or not words:return []
all_len = sum(map(len, words))
n = len(s)
words = Counter(words)
res = []
for i in range(0, n - all_len + 1):
tmp = s[i:i+all_len]
flag = True
for key in words:
if words[key] != tmp.count(key):
flag = False
break
if flag:res.append(i)
return res

但是比如: s = "ababaab" ,words = ["ab","ba","ba"]就会报错!

错误原因,因为计算时候我们会从字符串中间计算,也就是说会出现单词截断的问题.

所以我想另一种方法,

思路一:

因为单词长度固定的,我们可以计算出截取字符串的单词个数是否和words里相等,所以我们可以借用哈希表.

一个是哈希表是words,一个哈希表是截取的字符串,

比较两个哈希是否相等!

因为遍历和比较都是线性的,所以时间复杂度 :\(O(n^2)\)


上面思路每次都要反复遍历s;

下面介绍滑动窗口.

思路二:

滑动窗口!

我们一直在s维护着所有单词长度总和的一个长度队列!

关于滑动窗口,可以看看这篇文章.

时间复杂度:\(O(n)\)

还可以再优化,只是加一些判断,详细看代码吧!


关注我的知乎专栏,了解更多的解题技巧,大家一起进步,加油!

代码:

思路一:

python

class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
from collections import Counter
if not s or not words:return []
one_word = len(words[0])
all_len = len(words) * one_word
n = len(s)
words = Counter(words)
res = []
for i in range(0, n - all_len + 1):
tmp = s[i:i+all_len]
c_tmp = []
for j in range(0, all_len, one_word):
c_tmp.append(tmp[j:j+one_word])
if Counter(c_tmp) == words:
res.append(i)
return res

java

class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if (s == null || s.length() == 0 || words == null || words.length == 0) return res;
HashMap<String, Integer> map = new HashMap<>();
int one_word = words[0].length();
int word_num = words.length;
int all_len = one_word * word_num;
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
for (int i = 0; i < s.length() - all_len + 1; i++) {
String tmp = s.substring(i, i + all_len);
HashMap<String, Integer> tmp_map = new HashMap<>();
for (int j = 0; j < all_len; j += one_word) {
String w = tmp.substring(j, j + one_word);
tmp_map.put(w, tmp_map.getOrDefault(w, 0) + 1);
}
if (map.equals(tmp_map)) res.add(i);
}
return res;
}
}

思路二:

python

class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
from collections import Counter
if not s or not words:return []
one_word = len(words[0])
word_num = len(words)
n = len(s)
words = Counter(words)
res = []
for i in range(0, one_word):
cur_cnt = 0
left = i
right = i
cur_Counter = Counter()
while right + one_word <= n:
w = s[right:right + one_word]
right += one_word
cur_Counter[w] += 1
cur_cnt += 1
while cur_Counter[w] > words[w]:
left_w = s[left:left+one_word]
left += one_word
cur_Counter[left_w] -= 1
cur_cnt -= 1
if cur_cnt == word_num :
res.append(left)
return res

java

class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if (s == null || s.length() == 0 || words == null || words.length == 0) return res;
HashMap<String, Integer> map = new HashMap<>();
int one_word = words[0].length();
int word_num = words.length;
int all_len = one_word * word_num;
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
for (int i = 0; i < one_word; i++) {
int left = i, right = i, count = 0;
HashMap<String, Integer> tmp_map = new HashMap<>();
while (right + one_word <= s.length()) {
String w = s.substring(right, right + one_word);
tmp_map.put(w, tmp_map.getOrDefault(w, 0) + 1);
right += one_word;
count++;
while (tmp_map.getOrDefault(w, 0) > map.getOrDefault(w, 0)) {
String t_w = s.substring(left, left + one_word);
count--;
tmp_map.put(t_w, tmp_map.getOrDefault(t_w, 0) - 1);
left += one_word;
}
if (count == word_num) res.add(left); }
} return res;
}
}

再优化:

python

class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
from collections import Counter
if not s or not words:return []
one_word = len(words[0])
word_num = len(words)
n = len(s)
if n < one_word:return []
words = Counter(words)
res = []
for i in range(0, one_word):
cur_cnt = 0
left = i
right = i
cur_Counter = Counter()
while right + one_word <= n:
w = s[right:right + one_word]
right += one_word
if w not in words:
left = right
cur_Counter.clear()
cur_cnt = 0
else:
cur_Counter[w] += 1
cur_cnt += 1
while cur_Counter[w] > words[w]:
left_w = s[left:left+one_word]
left += one_word
cur_Counter[left_w] -= 1
cur_cnt -= 1
if cur_cnt == word_num :
res.append(left)
return res

java

class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if (s == null || s.length() == 0 || words == null || words.length == 0) return res;
HashMap<String, Integer> map = new HashMap<>();
int one_word = words[0].length();
int word_num = words.length;
int all_len = one_word * word_num;
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
for (int i = 0; i < one_word; i++) {
int left = i, right = i, count = 0;
HashMap<String, Integer> tmp_map = new HashMap<>();
while (right + one_word <= s.length()) {
String w = s.substring(right, right + one_word);
right += one_word;
if (!map.containsKey(w)) {
count = 0;
left = right;
tmp_map.clear();
} else {
tmp_map.put(w, tmp_map.getOrDefault(w, 0) + 1);
count++;
while (tmp_map.getOrDefault(w, 0) > map.getOrDefault(w, 0)) {
String t_w = s.substring(left, left + one_word);
count--;
tmp_map.put(t_w, tmp_map.getOrDefault(t_w, 0) - 1);
left += one_word;
}
if (count == word_num) res.add(left);
}
}
}
return res;
}
}

[LeetCode] 30. 串联所有单词的子串的更多相关文章

  1. Java实现 LeetCode 30 串联所有单词的子串

    30. 串联所有单词的子串 给定一个字符串 s 和一些长度相同的单词 words.找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置. 注意子串要与 words 中的单词完全匹配, ...

  2. Leetcode 30 串联所有单词的子串 滑动窗口+map

    见注释.滑动窗口还是好用. class Solution { public: vector<int> findSubstring(string s, vector<string> ...

  3. [LeetCode] 30. 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 ...

  4. [LeetCode] 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 ...

  5. 【LeetCode-面试算法经典-Java实现】【030-Substring with Concatenation of All Words(串联全部单词的子串)】

    [030-Substring with Concatenation of All Words(串联全部单词的子串)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Yo ...

  6. Leetcode 30.与所有单词相关联的子串

    与所有单词相关联的字串 给定一个字符串 s 和一些长度相同的单词 words.在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置. 注意子串要与 words 中的单词完全匹配,中间不能 ...

  7. [leetcode] 30. 与所有单词相关联的字串(cn第653位做出此题的人~)

    30. 与所有单词相关联的字串 这个题做了大概两个小时左右把...严重怀疑leetcode的judge机器有问题.同样的代码交出来不同的运行时长,能不能A题还得看运气? 大致思路是,给words生成一 ...

  8. Leetcode——30.与所有单词相关联的字串【##】

    @author: ZZQ @software: PyCharm @file: leetcode30_findSubstring.py @time: 2018/11/20 19:14 题目要求: 给定一 ...

  9. 【LeetCode 30】串联所有单词的子串

    题目链接 [题解] 开个字典树记录下所有的单词. 然后注意题目的已知条件 每个单词的长度都是一样的. 这就说明不会出现某个字符串是另外一个字符串的前缀的情况(除非相同). 所以可以贪心地匹配(遇到什么 ...

随机推荐

  1. JavaWeb面试篇(6)

    51.说一说Servlet的生命周期? Servlet有良好的生存期的定义,包括加载和实例化.初始化.处理请求以及服务结束.这个生存期由javax.servlet.Servlet接口的init(),s ...

  2. LeetCode - 乘积最大子串

    给定一个整数数组 nums ,找出一个序列中乘积最大的连续子串(该序列至少包含一个数). 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6. 示例 2: ...

  3. 为什么要重写hashcode( )和equals( )?

    打个比方,一个名叫张三的人去住酒店,在前台登记完名字就去了99层100号房间,此时警察来前台找叫张三的这个人住在哪间房,经过查询,该酒店住宿的有50个叫张三的,需要遍历查询,查询起来很不方便. 那么就 ...

  4. php大文件上传支持断点上传

    文件夹数据库处理逻辑 publicclass DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject(); ...

  5. Elastic-Job介绍

    1 什么是分布式任务调度 什么是分布式?当前软件的架构正在逐步转变为分布式架构,将单体结构分为若干服务,服务之间通过网络交互来完成用户的业务处理,如下图,电商系统为分布式架构,由订单服务.商品服务.用 ...

  6. Selenium 元素常用操作方法(键盘和鼠标事件)

    一.简单操作 click():点击 send_keys():输入 clear():清空 submit():提交表单 size:返回元素的尺寸 text:获取元素的文本 get_attribute(): ...

  7. 3D Computer Grapihcs Using OpenGL - 13 优化矩阵

    上节说过矩阵是可以结合的,而且相乘是按照和应用顺序相反的顺序进行的.我们之前初始化translationMatrix和rotationMatrix的时候,第一个参数都是使用的一个初始矩阵 glm::m ...

  8. 误用 Kotlin 中的 sortedWith() 方法排序,集合没有变化

    时间:2019年8月4日14:17:06问题描述:看下边的小例子: data class Man(val name: String, val age: Int, val type: Int) fun ...

  9. legend3---OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 10054

    legend3---OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 10054 一.总结 一句话总结: 解决方法:多试几次,实在不行就手动下载 1.homeste ...

  10. mysql高水位问题解决办法

    数据库中有些表使用delete删除了一些行后,发现空间并未释放产生原因:类比Oracle的高水位线产生原理 delete 不会释放文件高水位 truncate会释放 ,实际是把.ibd文件删掉了,再建 ...