4.4.2 python 字串雙指標/雜湊演算法2 —— Substring with Concatenation of All Words & Group Anagrams
這兩道題目都很巧妙的應用了雜湊演算法,可以作為雜湊演算法的應用講解,後面介紹雜湊的時候就不再做題了哈。
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 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.
題目解析
該題的思路是這樣的:
- 江words做成字典,可以理解為編碼;
- 匹配的過程就是,new_map控制與words的匹配過程,直到new_map與word_map相等,matched == len(words),此時start的位置是我們需要的結果,start+total 就是與words吻合的部分。
- 優化思路,外層for迴圈只有word_len長度,,因此效能不錯。充分利用new_map,從頭走到尾,不回溯,用start 記錄起始索引,當超過長度時,start 後移,new_map減少。
class Solution:
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
from collections import Counter
if not s or not words or not words[0]: return []
ret = []
word_len = len(words[0])
word_map = dict(Counter(words))
total = len(words) * word_len
for i in range(word_len):
new_map = {}
matched = 0
start = i
for j in range(i, len(s) - word_len + 1, word_len):
if j - start >= total:
old_word = s[start:start + word_len]
if old_word in new_map:
new_map[old_word] -= 1
if new_map[old_word] < word_map[old_word]:
matched -= 1
start += word_len
word = s[j: j + word_len]
if word in word_map: # 與word_map匹配的過程
new_map[word] = new_map.get(word, 0) + 1
if new_map[word] <= word_map[word]:
matched += 1
if matched == len(words):
ret.append(start)
return ret
49. Group Anagrams
Given an array of strings, group anagrams together.
Example:
Input: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
Output:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
Note:
All inputs will be in lowercase.
The order of your output does not matter.
題目解析
題目不難,下面的解法巧妙的構建了字典的key,text = "".join(sorted(s))
,即所有字母排序後拼接。最後列表推導式取出字典的value,可謂非常簡潔奇妙的方法。
class Solution:
def groupAnagrams(self, strs):
"""
:type strs: List[str]
:rtype: List[List[str]]
"""
dict_ = {}
for s in strs:
text = "".join(sorted(s))
dict_[text] = dict_.get(text, [])
dict_[text].append(s)
return [ele for ele in dict_.values()]