Hone logo
Hone
Problems

Implementing a Patricia Trie in JavaScript

Patricia Tries, also known as Radix Tries or compressed tries, are a space-efficient data structure for storing strings. They combine the advantages of tries and hash tables by compressing common prefixes, leading to reduced memory usage and faster lookups compared to standard tries, especially when dealing with a large number of strings sharing long prefixes. Your task is to implement a Patricia Trie data structure in JavaScript.

Problem Description

You are required to implement a Patricia Trie data structure in JavaScript. This data structure should support the following operations:

  • insert(str): Inserts a string str into the trie.
  • search(str): Searches for a string str in the trie. Returns true if the string exists, false otherwise.
  • startsWith(prefix): Checks if any string in the trie starts with the given prefix. Returns true if at least one string starts with the prefix, false otherwise.
  • delete(str): Deletes a string str from the trie.

The Patricia Trie should be implemented using nodes that represent prefixes. Each node should store a prefix string and a map of child nodes, where the keys of the map are single characters. When a node's prefix is a prefix of another node's prefix, the nodes should be merged to compress the trie.

Key Requirements:

  • The implementation should be efficient in terms of both space and time complexity.
  • The trie should handle empty strings correctly.
  • The delete operation should correctly remove the string and potentially merge nodes to maintain the compressed structure.
  • The implementation should be robust and handle various edge cases.

Expected Behavior:

The trie should behave as a standard trie but with the added benefit of prefix compression. The insert, search, startsWith, and delete operations should function correctly according to their standard definitions, while leveraging the Patricia Trie's compression capabilities.

Edge Cases to Consider:

  • Inserting duplicate strings.
  • Deleting a string that doesn't exist.
  • Searching for a string that doesn't exist.
  • Empty prefixes and strings.
  • Deleting a string that is a prefix of another string.
  • Merging nodes during insertion and deletion to maintain compression.

Examples

Example 1:

Input:
insert("hello")
insert("helloworld")
insert("hel")
search("hello")
search("world")
startsWith("hel")
startsWith("he")
delete("hello")
search("hello")

Output:

true
false
true
true
false

Explanation: The trie is initially populated with "hello", "helloworld", and "hel". "hello" and "helloworld" share the prefix "hello". "hel" is a separate entry. Searching for "hello" returns true. Searching for "world" returns false. "startsWith("hel")" returns true because "hel" is present. "startsWith("he")" returns true because "hello" and "hel" start with "he". Deleting "hello" removes the "hello" entry, and the "helloworld" node is updated to directly descend from the root. Searching for "hello" after deletion returns false.

Example 2:

Input:
insert("")
search("")
insert("a")
search("a")
startsWith("")
delete("")
search("")

Output:

true
true
true
false

Explanation: Inserting an empty string allows searching for it. Inserting "a" adds a new node. startsWith("") should return true as all strings are prefixes of the empty string. Deleting the empty string removes it. Searching for the empty string after deletion returns false.

Example 3: (Edge Case - Deletion and Merging)

Input:
insert("abc")
insert("ab")
delete("abc")
search("abc")
search("ab")
startsWith("ab")

Output:

false
true
true

Explanation: Inserting "abc" and "ab" creates a trie structure. Deleting "abc" leaves "ab" as a standalone node. Searching for "abc" returns false, while searching for "ab" returns true. startsWith("ab") returns true.

Constraints

  • The length of each string will be between 0 and 1000 characters (inclusive).
  • The number of strings inserted into the trie will be between 0 and 10000 (inclusive).
  • The implementation should have a time complexity of O(k) for search, startsWith, and delete, where k is the length of the string or prefix. insert should also be O(k).
  • The implementation should use reasonable memory. Excessive memory usage will be penalized.

Notes

  • Consider how to efficiently merge nodes during insertion and deletion to maintain the Patricia Trie's compressed structure.
  • Think about how to handle edge cases such as empty strings and duplicate insertions.
  • A good understanding of tries and hash tables will be helpful in implementing this data structure.
  • The root node of the Patricia Trie can be considered to have an empty prefix.
  • Focus on creating a clean, well-documented, and efficient implementation.
Loading editor...
javascript