208. Implement Trie (Prefix Tree)
A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
Trie()
Initializes the trie object.void insert(String word)
Inserts the string word into the trie.boolean search(String word)
Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.boolean startsWith(String prefix)
Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.void insert(String word)
key
, 나머지 글자를 통해 만든 Trie
를 value
로 하는 Map
을 이용key
에 해당하는 value
가 있다면, 재귀적으로 insert(substring)
을 하고, 없다면 새로 만들어서 넣은 후에 재귀적으로 insert(substring)
을 요청한다.substring
: word
에서 맨 앞글자를 제거한 stringboolean search(String word)
Map
에 word
의 맨 앞글자를 key로 하는 값을 요청한다.false
를 반환search(String substring)
를 요청하도록 함substring
의 길이가 0인 경우, 해당 문자로 끝나는지 확인함 (isEnd
)boolean startsWith(String prefix)
Map
에 word
의 맨 앞글자를 key로 하는 값을 요청한다.false
를 반환startsWith(String substring)
를 요청하도록 함substring
의 길이가 0인 경우, true
를 반환1차 답안 (최대한 통과시키는 것에 집중함)
class Trie {
private final Map<Character, Trie> children;
private boolean isEnd;
public Trie() {
children = new HashMap<>();
isEnd = false;
}
public void insert(String word) {
if (word.length() == 0) {
isEnd = true;
return;
}
Character key = word.charAt(0);
Trie child = children.get(key);
if (child == null) {
child = new Trie();
children.put(key, child);
}
child.insert(word.substring(1));
}
public boolean search(String word) {
if (word.length() == 0) {
return isEnd;
}
Character key = word.charAt(0);
Trie child = children.get(key);
if (child == null) {
return false;
}
return child.search(word.substring(1));
}
public boolean startsWith(String prefix) {
if (prefix.length() == 0) {
return true;
}
Character key = prefix.charAt(0);
Trie child = children.get(key);
if (child == null) {
return false;
}
return child.startsWith(prefix.substring(1));
}
}
리팩토링 제거
class Trie {
private final Map<Character, Trie> children;
private boolean isEnd;
public Trie() {
children = new HashMap<>();
isEnd = false;
}
public void insert(String word) {
if (word.length() == 0) {
isEnd = true;
return;
}
Trie child = getChild(word);
if (child == null) {
child = putNewChild(word);
}
child.insert(word.substring(1));
}
public boolean search(String word) {
if (word.length() == 0) {
return isEnd;
}
Trie child = getChild(word);
return child != null && child.search(word.substring(1));
}
public boolean startsWith(String prefix) {
if (prefix.length() == 0) {
return true;
}
Trie child = getChild(prefix);
return child != null && child.startsWith(prefix.substring(1));
}
private Trie getChild(String word) {
Character key = word.charAt(0);
return children.get(key);
}
private Trie putNewChild(String word) {
Character key = word.charAt(0);
Trie child = new Trie();
children.put(key, child);
return child;
}
}
a
는 0번째 ~ z
는 25번째의 형식으로 구현getChild
, putNewChild
를 분리해 놓아 자료구조를 바꾸기 용이했다.Map
대신 배열을 사용해서 성능을 높일 수 있었다.class Trie {
private static final int COUNT_OF_LETTERS = 26;
private static final char START_LETTER = 'a';
private final Trie[] children;
private boolean isEnd;
public Trie() {
children = new Trie[COUNT_OF_LETTERS];
isEnd = false;
}
public void insert(String word) {
if (word.length() == 0) {
isEnd = true;
return;
}
Trie child = getChild(word);
if (child == null) {
child = putNewChild(word);
}
child.insert(word.substring(1));
}
public boolean search(String word) {
if (word.length() == 0) {
return isEnd;
}
Trie child = getChild(word);
return child != null && child.search(word.substring(1));
}
public boolean startsWith(String prefix) {
if (prefix.length() == 0) {
return true;
}
Trie child = getChild(prefix);
return child != null && child.startsWith(prefix.substring(1));
}
private Trie getChild(String word) {
char key = word.charAt(0);
return children[key - START_LETTER];
}
private Trie putNewChild(String word) {
char key = word.charAt(0);
Trie child = new Trie();
children[key - START_LETTER] = child;
return child;
}
}