题目
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:
s = “barfoothefoobarman”,
words = [“foo”,“bar”]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 “barfoo” 和 “foobar” 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:
s = “wordgoodgoodgoodbestword”,
words = [“word”,“good”,“best”,“word”]
输出:[]
思路:
我开始的想法是先把words
里的单词全排列,然后在s
里找。。。。这样也行,但是太慢了。。。。。
后来看了评论的题解,运用了滑动窗口和哈希表来解题。
滑动窗口的大小就是words
中所有单词的长度。一次滑动一格,依次判断滑动窗口里的字符串是否符合要求。
如何确定滑动窗口内的字符串是由words
里的字符串排列组成的呢?这个时候就要用到哈希表。
给words
建立哈希表,键是字符串,值是字符串在words
中出现的次数。给滑动窗口里的字符串也建立哈希表;如果和words
上的哈希表一样,说明此时的字符串符合要求。
代码:
class Solution(object):
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
if not s or not words:
return []
from collections import Counter
aim = []
l = len(words[0])
length = l*len(words)
Cwords = Counter(words)
for i in range(len(s)):
if i+length > len(s):
break
temp = s[i:i+length]
array = []
for j in range(len(words)):
array.append(temp[j*l:(j+1)*l])
array = Counter(array)
if array == Cwords:
aim.append(i)
return aim
顺便记录一下两种全排列的算法:
第一种是两两交换:
aim = []
def Perm(array, m, n):
if m==n:
temp = copy.copy(array)
aim.append(temp)
return
else:
i = m
while i<n:
array[m], array[i] = array[i], array[m]
Perm(array, m+1, n)
array[m], array[i] = array[i], array[m]
i +=1
第二种类似深搜,建立一颗树:
aim = []
#array是待排列的字符串;result存结果,初始化为空。
#每次递归都往result加一个字符
def Permut(array, result):
if not array:
aim.append(result)
return
for i in range(len(array)):
temp = copy.copy(result)
temp.append(array[i])
temp1 = copy.copy(array)
temp1.remove(array[i])
Permut(temp1, temp)