-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTrie.java
92 lines (72 loc) · 3.2 KB
/
Trie.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/**
* Implement Trie (Prefix Tree)
*
* Implement a trie with insert, search, and startsWith methods.
*
* Note: You may assume that all inputs are consist of lowercase letters a-z. All inputs are guaranteed to be non-empty strings.
*
* e.g.
* Trie trie = new Trie();
* trie.insert("apple");
* trie.search("apple"); // returns true
* trie.search("app"); // returns false
* trie.startsWith("app"); // returns true
*
* Big Picture: Tries useful in various applications like autocomplete, spell checker, IP routing (longest prefix matching), etc.
*
* N.B. Trie (pronounced as 'try') is a fixed tree data structure that outperforms hash tables -- hash tables do have
* constant O(1) time complexity for key lookup but are inefficient wrt finding all keys with common prefix. Also,
* hash tables will run into hash collisions with an increasing hash table size causing search to slow to O(n) where n is
* number of keys. Tries can use less space compared to hash tables when storing many keys with the same prefix.
*
* Complexity:
* Insert into Trie: O(m) (where m is key length) time and space
* Search Trie: O(m) time and O(1) space
* Search Prefix/startsWith: O(m) time and O(1) space
*/
public class Trie {
public static class TrieNode {
private TrieNode[] links;
private boolean isEnd;
public TrieNode() { links = new TrieNode[26]; } // a-z length = 26
public boolean containsKey(char c) { return links[c - 'a'] != null; }
public TrieNode get(char c) { return links[c - 'a']; }
public void put(char c, TrieNode node) { links[c - 'a'] = node; }
public void setEnd() { isEnd = true; }
public boolean isEnd() { return isEnd; }
}
private TrieNode root;
public Trie() { root = new TrieNode(); }
public static void main(String[] args) {
Trie t = new Trie();
t.insert("apple");
System.out.println(t.search("app")); // false
System.out.println(t.startsWith("app")); // true
}
public void insert(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char curr = word.charAt(i);
if (!node.containsKey(curr)) { node.put(curr, new TrieNode()); }
node = node.get(curr);
}
node.setEnd();
}
private TrieNode prefixSearch(String word) { // search entire or partial trie
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char curr = word.charAt(i);
if (node.containsKey(curr)) { node = node.get(curr); }
else { return null; }
}
return node; // returns node where search ends
}
public boolean search(String word) {
TrieNode node = prefixSearch(word);
return node != null && node.isEnd(); // returns true if the word is in trie
}
public boolean startsWith(String prefix) {
TrieNode node = prefixSearch(prefix);
return node != null;
}
}