Implement Trie (Prefix Tree)

Problem

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.

Implement the Trie class:

  • 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.

Example 1:

Input
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
Output
[null, null, true, false, true, null, true]

Explanation
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple");   // return True
trie.search("app");     // return False
trie.startsWith("app"); // return True
trie.insert("app");
trie.search("app");     // return True

Intuition

The task is to design a data structure that supports adding new words and finding if a string matches any previously added string. The key challenge is to handle wildcard characters (dots) in the search queries, where dots can match any letter. To achieve this, we can use a Trie (prefix tree) data structure, where each node represents a character in a word.

Approach

Trie Node:

Implement a TrieNode class with attributes:
children: A dictionary mapping characters to child nodes.
is_end_of_word: A boolean indicating whether the current node marks the end of a word.
WordDictionary Class:

Implement a WordDictionary class with methods:
init: Initializes an empty Trie with a root node.
addWord: Inserts a word into the Trie by iterating over its characters and creating nodes as needed. The last node of the word is marked as the end of a word.
search: Searches for a word in the Trie, handling wildcard characters. Recursively explores all possible paths in the Trie for wildcard characters.
Insertion:

During insertion, iterate over each character of the word.
If the character is not already a child of the current node, create a new child node.
Move to the next node and repeat the process until all characters are inserted. Mark the last node as the end of a word.
Search:

During search, iterate over each character of the word.
If a character is a wildcard ('.'), explore all possible paths by recursively searching the Trie for the remaining characters.
If a character is not a wildcard, check if it is a child of the current node.
Return True only if the end of a valid word is reached.

Complexity

  • Time complexity:

Insertion: The time complexity of insertion is O(m), where m is the length of the word being inserted.
Search: The time complexity of search depends on the number of wildcard characters in the query. In the worst case, where there are k wildcard characters, the time complexity is O(26^k * m), where m is the length of the word.

  • Space complexity:

The space complexity of the Trie depends on the number of unique words and the length of the words. In the worst case, where there are no common prefixes among the words, the space complexity is O(n * m), where n is the number of words and m is the average length of the words. The space complexity is dominated by the Trie structure.

Code

class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end_of_word = False

class WordDictionary:
    def __init__(self):
        self.root = TrieNode()

    def addWord(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.is_end_of_word = True

    def search(self, word):
        return self._search_word(self.root, word)

    def _search_word(self, node, word):
        for i, char in enumerate(word):
            if char == '.':
                for child in node.children.values():
                    if self._search_word(child, word[i + 1:]):
                        return True
                return False
            elif char not in node.children:
                return False
            node = node.children[char]

        return node.is_end_of_word

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-27 19:04:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-27 19:04:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-27 19:04:02       82 阅读
  4. Python语言-面向对象

    2024-01-27 19:04:02       91 阅读

热门阅读

  1. Oracle 数据库(卸载)详细过程

    2024-01-27 19:04:02       60 阅读
  2. spring自动配置的原理

    2024-01-27 19:04:02       52 阅读
  3. 【重点问题】攻击面发现及管理

    2024-01-27 19:04:02       56 阅读
  4. 深度学习在医学影像分析中的应用

    2024-01-27 19:04:02       55 阅读
  5. 11Docker数据持久化

    2024-01-27 19:04:02       52 阅读
  6. docker运行nginx不生效

    2024-01-27 19:04:02       61 阅读
  7. Golang协程池ants使用笔记

    2024-01-27 19:04:02       62 阅读
  8. Vue3 封装Tree树形组件,且只支持单选

    2024-01-27 19:04:02       51 阅读
  9. 开发嵌入式Linux应用程序框架-QT的初步了解

    2024-01-27 19:04:02       53 阅读