package com.freetymekiyan.algorithms.level.medium;
import org.junit.Assert;
import org.junit.Test;
/**
* Implement a trie with insert, search, and startsWith methods.
* <p>
* Note:
* You may assume that all inputs are consist of lowercase letters a-z.
* <p>
* Company Tags: Google, Uber, Facebook, Twitter, Microsoft, Bloomberg
* Tags: Design, Trie
* Similar Problems: (M) Add and Search Word - Data structure design
*/
public class ImplementTrie {
@Test
public void testStartsWith() {
Trie trie = new Trie();
Assert.assertFalse(trie.startsWith(null));
Assert.assertTrue(trie.startsWith(""));
trie.insert("key");
Assert.assertTrue(trie.startsWith(""));
Assert.assertTrue(trie.startsWith("ke"));
Assert.assertFalse(trie.startsWith("ka"));
Assert.assertTrue(trie.startsWith("key"));
Assert.assertFalse(trie.startsWith("keys"));
trie.insert("ke");
Assert.assertTrue(trie.startsWith("ke"));
Assert.assertFalse(trie.startsWith("search"));
}
@Test
public void testSearch() {
Trie trie = new Trie();
Assert.assertFalse(trie.search(null));
Assert.assertFalse(trie.search(""));
Assert.assertFalse(trie.search("key"));
trie.insert("key");
Assert.assertTrue(trie.search("key"));
Assert.assertFalse(trie.search("ke"));
trie.insert("kevin");
Assert.assertFalse(trie.search("ke"));
Assert.assertTrue(trie.search("key"));
Assert.assertTrue(trie.search("kevin"));
trie.insert("kiyan");
Assert.assertFalse(trie.search("ke"));
Assert.assertTrue(trie.search("kiyan"));
trie.insert("ke");
Assert.assertTrue(trie.search("ke"));
}
class TrieNode {
private final int R = 26;
private TrieNode[] links;
private boolean end;
// Initialize your data structure here.
public TrieNode() {
links = new TrieNode[R];
}
public boolean hasLink(char ch) {
return links[ch - 'a'] != null;
}
public TrieNode getNode(char ch) {
return links[ch - 'a'];
}
public void putNode(char ch) {
links[ch - 'a'] = new TrieNode();
}
public void setEnd() {
end = true;
}
public boolean isEnd() {
return end;
}
}
public class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
// Inserts a word into the trie.
public void insert(String word) {
if (word == null) {
return;
}
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (!node.hasLink(c)) {
node.putNode(c);
}
node = node.getNode(c);
}
node.setEnd();
}
// search a prefix or whole key in trie and
// returns the node where search ends
private TrieNode searchPrefix(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (!node.hasLink(c)) {
return null;
}
node = node.getNode(c);
}
return node;
}
// Returns if the word is in the trie.
public boolean search(String word) {
if (word == null) {
return false;
}
TrieNode node = searchPrefix(word);
return node != null && node.isEnd(); // Note to check node.isEnd().
}
// Returns if there is any word in the trie
// that starts with the given prefix.
public boolean startsWith(String prefix) {
if (prefix == null) {
return false;
}
TrieNode node = searchPrefix(prefix);
return node != null;
}
}
// Your Trie object will be instantiated and called as such:
// Trie trie = new Trie();
// trie.insert("somestring");
// trie.search("key");
}