You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
Example 1:
Input: s = "barfoothefoobarman", words = ["foo","bar"] Output: [0, 9] Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively. The output order does not matter, returning [9,0] is fine too.
Example 2:
Input: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"] Output: []
思路
在一开始做这道题时,想着从头到尾一直遍历使用暴力破解法来解决,但是在编码完成之后,一直不通过。最终看了以下答案。发现整体思路都是一样的只不过在细节上处理上更加厉害。
这道题的整体思路是先将words列表中的单词转化为字典,然后进行遍历来判断是否存在字符串中。详细见代码。
解决代码
1 class Solution(object):
2 def findSubstring(self, s, words):
3 """
4 :type s: str
5 :type words: List[str]
6 :rtype: List[int]
7 """
8 from collections import Counter
9 if not s or not words:
10 return []
11 word_size = len(words[0]) # 因为每一个单词长度一样,求出其中一个单词的长度
12 word_map = Counter(words) # 将words列表中的单词进行计数统计
13 results = [] # 存储结果
15 num_word = len(words) # 单词的总数
16 list_size = word_size*num_word # 所有单词的总长度
17 for i in range(len(s)-list_size+1): # 只需要遍历到 s的长度减去单词的总长度的位置就行了,因为后面的不会满足条件。
18 seen = dict(word_map) # 临时字典,存储的是每个单词的出现次数
19 word_used = 0
20 for j in range(i, i+list_size, word_size): # 从 第i个位置开始,到所有单词总长度的位置,意思是判断这一部分是否满足条件。
21 sub_str = s[j:j+word_size] # 在s中提取相应单词长度的字符串。
22 if sub_str in seen and seen[sub_str] >0: # 如果提出出的字符串在seen字典中,并且相应的值不为0
23 seen[sub_str] -= 1 # 相应字符串的值减一,
24 word_used += 1 # 匹配的数目加一
25 else:
26 break # 如果不满足,直接返回,后面不会存在满足添加的可能。
27 if word_used == num_word: # 相等则表明所有的都匹配完。
28 results.append(i) # 存储下标
29 return results