こんにちは
今回の学びは
・implement-trie-prefix-tree Trieは実装できるようになろう!
この問題はTrieの基本です。重要な問題と思います。
(時間配分は5分問題理解=restate&clarify 10分検討multip-sol, analysis, reasons 10分実装 20分振り返り の一文45分構成)をできればgoogle docで笑&真剣。
終始、わからないことは声にだして、明確にしていきましょう。
1,まずは入出力をしっかりおさえましょう。(問題を自分の言葉で復唱すること、わからないことをクリアにすると、前提も声にだすこと)
2,いくつかのソリューションを声にだして出してみましょう。(もちろんtime complexit, space complexityの分析や理由を付け加えて)
3,どれでいくか、一緒に決定しましょう。(理由付きでね、よろしく)
timespace analysis (時間とスペースの分析)は 〇〇です
場合によっては、pseudocode(擬似コード)をかいてみてもよい。
https://leetcode.com/problems/implement-trie-prefix-tree/ apple apo a -> p -> p-> -> l -> e -> o calss Node: value next_nodes is_end = False Node(a), ... Node(z) sO( 26 ^ n ) # doesn't scale, but , but realisticcly, there only about 2M words. so let's do this. { a: {p: { p: { l: {e : {a: {}, end:1}} o: # Object, it can not track by index(key). Need to overwrite Dict { Na: {Pa: { p: { l: {e : {}} o: # Let's write in using dict(dict...) and "end" entry as flag # Let's write in using dict(dict...) and "end" entry as flag """ e: { v: { e: { n: { t: { end: {} } } end: {} } o: { l: {v:{e:{end:{}}}} } } } """ class Trie: self.__init__(): self.db = {} def insert(self, word: str) -> None: curr = self.db for i, c in enumerate(word): if i == len(word) - 1: curr[c].update({"end":1}) else: curr[c].update({}) curr = curr[c] def search(self, word: str) -> bool: # eve curr = self.db N = len(word) i = 0 while i <= N and curr and word[i] in curr: # N=2, curr = {...}, e in if i == len(word) -1 and "end" in curr[word[i]]: return True curr = curr[word[i]] i+=1 return False def startsWith(self, prefix: str) -> bool: curr = self.db N = len(prefix) i = 0 while i <= N and curr and word[i] in curr: # e in curr_db? if i == len(word) -1: return True curr = curr[word[i]] i+=1 return False
4、実装しましょう。
class Trie: def __init__(self): self.db = {} def insert(self, word: str) -> None: curr = self.db for i, c in enumerate(word): if c in curr: if i == len(word) - 1: curr[c].update({"end":{}}) else: curr[c].update({}) else: if i == len(word) - 1: curr[c] = {"end":{}} else: curr[c] = {} curr = curr[c] def search(self, word: str) -> bool: # eve curr = self.db N = len(word) i = 0 while i < N and curr and word[i] in curr: # N=2, curr = {...}, e in if i == len(word) -1 and "end" in curr[word[i]]: return True curr = curr[word[i]] i+=1 return False def startsWith(self, prefix: str) -> bool: curr = self.db N = len(prefix) i = 0 while i <= N and curr and prefix[i] in curr: # e in curr_db? if i == len(prefix) -1: return True curr = curr[prefix[i]] i+=1 return False # Your Trie object will be instantiated and called as such: trie = Trie() print(trie.insert("apple")) print(trie.search("apple")) # returns true print(trie.search("app")) # returns false print(trie.startsWith("app")) # returns true print(trie.insert("app")) print(trie.search("app")) # returns true
5、エッジケースとサンプルテストを忘れずに!
振り返り
「次のこの問題を解くばあい知っていればよい一つの事実とは?」
Trieをdictで実装する
最初に考えた、Nodeを作ってやるやり方は私は検索がNodeだとできないと思ったが
[0] * 26でインデックスの箱を用意してやるやり方があったか。
setdefaultでかなりスッキリ書かれているパターン
https://leetcode.com/problems/implement-trie-prefix-tree/discuss/486556/Python-using-setdefault
スピードはそこそこ、私のより20%くらい速く
(py37new) 0122 11:46 aoj > Runtime: 200 ms, faster than 34.64% of Python3 online submissions for Implement Trie (Prefix Tree).
なぜか、私の2回目流すと一気に74%に改善、するとsetdefaultは遅いか!?
setdefaultとははじめてのPython!setdefaultで辞書のキーと値を追加する方法でみると、単純な便利関数っぽい動き、もっとよいバージョンがdefaultdictだと思うけど、実際あんまりパフォーマンスはよくなかった感じがしたよ。本家にもちょっと使われているケースが違うけど、defaultdictのがシンプルで速いとかいてあった。まぁでも、この実装はsetdefaultを使っているだけで、構成は私のと同じですね。
まとめ
・implement-trie-prefix-tree Trieは実装できるようになろう!
・この問題はimplement-trie-prefix-treeはTrieの基本です。重要な問題と思います。
以上です