LeetCode30-與所有單詞相關聯的字串
https://zhuanlan.zhihu.com/p/51296482
這是我上午花了好長好長好處時間寫的一篇隨筆,該說的話都在這裡面了,我不會赤裸裸的跟大家說:我想推薦大家去看看的。啊哈哈哈哈。
30-與所有單詞相關聯的字串
給定一個字串 s 和一些長度相同的單詞 words。在 s 中找出可以恰好串聯 words 中所有單詞的子串的起始位置。
注意子串要與 words 中的單詞完全匹配,中間不能有其他字元,但不需要考慮 words 中單詞串聯的順序。
示例 1:
[0,9]
示例 2:
[]
這一題我剛開始做的時候是按照暴力法來做的,沒辦法啊,菜鳥的第一想法就是最簡單最容易理解的暴力搜尋法(其實是最容易想到的,其他更簡單的方法要是能想到,誰還用暴力法啊)
思路:
1)可以先將目標words陣列內的字串元素自由組合,python中可以使用itertools.permutations() 這個函式極為方便,能夠快速的生成給定陣列內元素的排列列表,並且列表內元素不允許重複出現,就跟數學中的排列是一樣的。
2)得到目標words陣列內的排列列表後,就可以依次遍歷字串 s了,只要字串中有與words陣列內的排列列表相等的字串,把對應的下標值記錄下來返回就可。
程式碼如下:
from itertools import permutations class Solution: # 可以先將word陣列內字串自由組合,然後用s.index()函式即可得到答案 # 要考慮字串s和words中出現的重複字元 # 此種解法超出時間限制 def findSubstring(self, s, words): """ :type s: str :type words: List[str] :rtype: List[int] """ if s is None or len(words) == 0 or len(s) < len(words[0] * len(words)): return [] if s is None or len(words) == 0 or len(s) < len(words[0] * len(words)): return [] # 採用itertools.permutations()函式將word陣列內字串自由組合,如[('foo', 'bar'), ('bar', 'foo')] words_permutations = permutations(words) words_list = set([]) # 然後依次遍歷words_permutations組合,找到與字串s對應位置相等的字串 # 完全的暴力法 for index in words_permutations: # 將words_permutations內某一種組合情況合併為一個字串(例如('foo', 'bar')合併為"foobar"),供後面使用 index = ''.join(list(index)) if index in s: start = s.index(index) words_list.add(start) for i in range(start, len(s)-len(index)+1): if s[i:i+len(index)] == index: words_list.add(i) return list(words_list) if __name__ == "__main__": s = "barfoothefoobarman" words = ["foo","bar"] result = Solution().findSubstring(s, words) print(result)
是不是感覺很簡單,但是要潑一盆冷水的是:最後超出時間限制了,真的是要捶人啊!這是要逼我祭出大招啊——去找度娘,度娘始終是不會讓我失望的,終於是找到了一種更為巧妙的方法。上面的暴力法之所以花費時間較多,是因為我們考慮到了所有的排列情況,這才會時間爆炸,如果我們不需要去考慮排列情況,只需要單純的比較words 陣列對應的字串與字串 s 的關係,那時間豈不是能省去一大截。答案是:那踏馬肯定是的啊,我都說到這兒了,說的話肯定是對的啊,哈哈哈哈哈。那現在的關鍵就是如何省略排列情況這一步了。
思路:
1)每次從s中切對應長度(words中各個元素的長度之和)的一條子串,
2)然後再把這條子串按words中單個單詞的長度再切成更小子串構成一個list, 把words和list排序後的結果比對一下,看是否完全相同,如果是則我們返回對應的起始點。否則繼續。
程式碼如下:
class Solution:
# 每次從s中切對應長度(words中各個元素的長度之和)的一條子串,
# 然後再把這條子串按words中單個單詞的長度再切成更小子串構成一個list, 把words和list排序後的結果比對一下,
# 看是否完全相同,如果是則我們返回對應的起始點。否則繼續。
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
if s is None or len(words) == 0:
return []
word_length = len(words[0])
words_length = word_length * len(words)
words.sort()
word_list = []
for index in range(len(s) - words_length + 1):
sub_s = [s[index+i*word_length: index+(i+1)*word_length] for i in range(len(words))]
sub_s.sort()
if words == sub_s:
word_list.append(index)
return word_list
if __name__ == "__main__":
s = "aa"
words = ["aa", "af"]
result = Solution().findSubstring(s, words)
print(result)
是不是覺得so so so easy?別急,我還有更好的...好個屁了,寫到這兒已經虐的差不多了,人懶寫不動了,各位讀者要是有更好的想法也可以積極分享哈!