NeetCode 150 全問の解き方とポイントまとめ Tries

Tries
本記事は以下記事の一部です。
NeetCode 150 全問の解き方とポイントまとめ & 感想
TrieはTreesの発展でたった3問しかないですが、NeetCodeのRoad Mapでも独立している感じで、HeapやBacktrackingとまとめるのも変なので独立した記事にします。
61. Implement Trie Prefix Tree
Link | |
Related links | |
Difficulty (Easy, Medium, Hard) | Medium |
Time Complexity | O(M) ※Mはwordの長さ |
Space Complexity | O(N) ※Nは単語の合計長 |
The personal need for review (1 ~ 10) | 6 |
Memo |
|
Problem
A prefix tree (also known as a trie) is a tree data structure used to efficiently store and retrieve keys in a set of strings. Some applications of this data structure include auto-complete and spell checker systems.
Implement the PrefixTree class:
PrefixTree()Initializes the prefix tree object.void insert(String word)Inserts the stringwordinto the prefix tree.boolean search(String word)Returnstrueif the stringwordis in the prefix tree (i.e., was inserted before), andfalseotherwise.boolean startsWith(String prefix)Returnstrueif there is a previously inserted stringwordthat has the prefixprefix, andfalseotherwise.Example 1:
Input: ["Trie", "insert", "dog", "search", "dog", "search", "do", "startsWith", "do", "insert", "do", "search", "do"] Output: [null, null, true, false, true, null, true] Explanation: PrefixTree prefixTree = new PrefixTree(); prefixTree.insert("dog"); prefixTree.search("dog"); // return true prefixTree.search("do"); // return false prefixTree.startsWith("do"); // return true prefixTree.insert("do"); prefixTree.search("do"); // return trueCopy
Constraints:
1 <= word.length, prefix.length <= 1000wordandprefixare made up of lowercase English letters.
Solution
class TrieNode:
def __init__(self):
self.children = {} # alphabet -> TrieNode
self.endOfWord = False
class PrefixTree:
def __init__(self):
self.root = TrieNode()
def insert(self, word: str) -> None:
curr = self.root
for c in word:
if c not in curr.children:
curr.children[c] = TrieNode()
curr = curr.children[c]
curr.endOfWord = True
def search(self, word: str) -> bool:
curr = self.root
for c in word:
if c not in curr.children:
return False
curr = curr.children[c]
return curr.endOfWord
def startsWith(self, prefix: str) -> bool:
curr = self.root
for c in prefix:
if c not in curr.children:
return False
curr = curr.children[c]
return True62. Design Add And Search Words Data Structure
Link | https://neetcode.io/problems/design-word-search-data-structure |
Related links | |
Difficulty (Easy, Medium, Hard) | Medium |
Time Complexity | 最良ケース: O(M) 最悪ケース: O(N * 26^k) ※Mはwordの長さ |
Space Complexity | O(N) ※Nは単語の合計長 |
The personal need for review (1 ~ 10) | 8 |
Memo |
|
Problem
Design a data structure that supports adding new words and searching for existing words.
Implement the
WordDictionaryclass:
void addWord(word)Addswordto the data structure.bool search(word)Returnstrueif there is any string in the data structure that matcheswordorfalseotherwise.wordmay contain dots'.'where dots can be matched with any letter.Example 1:
Input: ["WordDictionary", "addWord", "day", "addWord", "bay", "addWord", "may", "search", "say", "search", "day", "search", ".ay", "search", "b.."] Output: [null, null, null, null, false, true, true, true] Explanation: WordDictionary wordDictionary = new WordDictionary(); wordDictionary.addWord("day"); wordDictionary.addWord("bay"); wordDictionary.addWord("may"); wordDictionary.search("say"); // return false wordDictionary.search("day"); // return true wordDictionary.search(".ay"); // return true wordDictionary.search("b.."); // return trueCopy
Constraints:
1 <= word.length <= 20wordinaddWordconsists of lowercase English letters.wordinsearchconsist of'.'or lowercase English letters.
Solution
class TrieNode:
def __init__(self):
self.children = {} # alphabet -> TrieNode
self.endOfWord = False
class WordDictionary:
def __init__(self):
self.root = TrieNode()
def addWord(self, word: str) -> None:
curr = self.root
for c in word:
if c not in curr.children:
curr.children[c] = TrieNode()
curr = curr.children[c]
curr.endOfWord = True
def search(self, word: str) -> bool:
def dfs(i: int, node: TrieNode) -> bool:
curr = node
for j in range(i, len(word)):
c = word[j]
if c == '.':
for child in curr.children.values():
if dfs(j+1, child):
return True
return False
else:
if c not in curr.children:
return False
curr = curr.children[c]
return curr.endOfWord
return dfs(0, self.root)63. Word Search II
Link | https://neetcode.io/problems/design-word-search-data-structure |
Related links | |
Difficulty (Easy, Medium, Hard) | Hard |
Time Complexity | O (N M 4^L) ※Lは最長の単語長 |
Space Complexity | トライ木: O(W * M) スタック: O(N * M) |
The personal need for review (1 ~ 10) | 9 |
Memo |
|
Problem
Given a 2-D grid of characters
boardand a list of stringswords, return all words that are present in the grid.For a word to be present it must be possible to form the word with a path in the board with horizontally or vertically neighboring cells. The same cell may not be used more than once in a word.
Example 1:
Input: board = [ ["a","b","c","d"], ["s","a","a","t"], ["a","c","k","e"], ["a","c","d","n"] ], words = ["bat","cat","back","backend","stack"] Output: ["cat","back","backend"]
Solution
class TrieNode:
def __init__(self):
self.children = {} # alphabet -> TridNode
self.endOfWord = False
class Solution:
def __init__(self):
self.root = TrieNode()
def addWord(self, word: str):
curr = self.root
for c in word:
if c not in curr.children:
curr.children[c] = TrieNode()
curr = curr.children[c]
curr.endOfWord = True
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
ROWS, COLS = len(board), len(board[0])
# up, right, down, left
DIRECTIONS = [[-1,0],[0,1],[1,0],[0,-1]]
for word in words:
self.addWord(word)
res = set()
visited = set()
def dfs(r: int, c: int, node: TrieNode, word: str) -> None:
if (r not in range(ROWS) or
c not in range(COLS) or
(r,c) in visited or
board[r][c] not in node.children
):
return
visited.add((r,c))
next_node = node.children[board[r][c]]
next_word = word + board[r][c]
if next_node.endOfWord:
res.add(next_word)
for dr, dc in DIRECTIONS:
nr, nc = dr + r, dc + c
dfs(nr, nc, next_node, next_word)
visited.remove((r,c))
for r in range(ROWS):
for c in range(COLS):
dfs(r, c, self.root, '')
return list(res)