1. 程式人生 > >4.4.2 python 字串雙指標/雜湊演算法2 —— Substring with Concatenation of All Words & Group Anagrams

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.

題目解析

該題的思路是這樣的:

  1. 江words做成字典,可以理解為編碼;
  2. 匹配的過程就是,new_map控制與words的匹配過程,直到new_map與word_map相等,matched == len(words),此時start的位置是我們需要的結果,start+total 就是與words吻合的部分。
  3. 優化思路,外層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()]