Trie

Insertion

We insert a key by starting at the root and searching for a link which corresponds to the first character:

  • If a link exists, move to that node
  • If not, add that node as a link to the current node and move to it
    • If we reach the end of the word, mark the last node as the end

Search

Each word is represented as a path from the root to a leaf node. We start from the root with the first character, looking for links corresponding to that character:

  • If the link exists, we move to the next node in the path following this link
  • If there’s no keys in the search word left and the node isn’t marked as isEnd, return false
  • Otherwise return true

Search Prefix

Exactly the same as searching for a word, but we don’t need to check isEnd.

class Trie() {
 
    private val root = TrieNode()
    
    fun insert(word: String) {
        var node = root
        for (char in word) {
            if (!node.containsKey(char)) {
                node.put(char, TrieNode())
            }
            
            node = node.get(char)!!
        }
		
        node.setEnd()
    }
 
    /**
	* Returns true if the entire word is in the Trie
	*/
    fun search(word: String): Boolean {
        var node = root
        for (char in word) {
            if (!node.containsKey(char)) return false
            
            node = node.get(char)!!
        } 
        
        return node.isEnd()
    }
 
	/**
	* Returns true if there is any word in the trie that starts with the
	* given prefix
	*/
    fun startsWith(prefix: String): Boolean {
        var node = root
        for (char in prefix) {
            if (!node.containsKey(char)) return false
            
            node = node.get(char)!!
        } 
        
        return true
    }
 
}
 
class TrieNode {
    
    private val NUM_CHARS = 26
    
    private val links = Array<TrieNode?>(NUM_CHARS) { null }
    
    private var isEnd = false
    
    fun containsKey(char: Char): Boolean {
        return links[char - 'a'] != null
    }
    
    fun get(char: Char): TrieNode? {
        return links[char - 'a']
    }
    
    fun put(char: Char, node: TrieNode) {
        links[char - 'a'] = node 
    }
    
    fun setEnd() {
        isEnd = true
    }
    
    fun isEnd() = isEnd
}