Trie in a Google Interview
The problem comes from Daily Coding Problem, here it is:
Good morning! Here's your coding interview problem for today.
This problem was asked by Google.
Implement a
PrefixMapSum
class with the following methods:insert(key: str, value: int)
: Set a given key's value in the map. If the key already exists, overwrite the value.sum(prefix: str)
: Return the sum of all values of keys that begin with a given prefix.
For example, you should be able to run the following code:
mapsum.insert("columnar", 3)
assert mapsum.sum("col") == 3
mapsum.insert("column", 2)
assert mapsum.sum("col") == 5
One way to solve this is to build a prefix trie in the following way:
- Start with a simple trie implementation: hash table for the children nodes, the cumulative val, whether the node is a word, and the value of the word
- When adding the word, set the cumulative along the way and check whether the current node is a word
- If it is, make sure to return the word value in a ref variable to be dealt with later
- In the outer code, when you're adding the word, if the word already exists (see #3), remove it from cumulative
- The prefix cumulative call becomes straightforward
This leads to a O(2*Len(word))-time insert cost, and O(Len(prefix))-time cumulative cost. Code is below and right here on Git: https://github.com/marcelodebarros/dailycodingproblem/blob/master/DailyCodingProbem05042019.cs
Cheers, ACC.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; namespace DailyCodingProblem { class DailyCodingProbem05042019 { public void Process() { PrefixSumTrie pst = new PrefixSumTrie(); pst.AddWord("foo", 5); pst.AddWord("foobar", 15); string prefix = "foo"; Console.WriteLine("Cummulative for {0}: {1}", prefix, pst.Cummulative(prefix)); pst.AddWord("foo", 15); Console.WriteLine("Cummulative for {0}: {1}", prefix, pst.Cummulative(prefix)); pst.AddWord("foofighters", 100); Console.WriteLine("Cummulative for {0}: {1}", prefix, pst.Cummulative(prefix)); } } class PrefixSumTrie { private Hashtable children = null; private bool isWord = false; private int cummulative = 0; private int wordVal = 0; public PrefixSumTrie() { children = new Hashtable(); isWord = false; cummulative = 0; wordVal = 0; } public void AddWord(string word, int val) { int previousVal = -1; AddWord(word, val, ref previousVal); if (previousVal > 0) { RemoveWord(word, previousVal); } } public int Cummulative(string prefix) { if (String.IsNullOrEmpty(prefix)) { return cummulative; } if (children.ContainsKey(prefix[0])) { return ((PrefixSumTrie)children[prefix[0]]).Cummulative(prefix.Substring(1)); } return 0; } private void AddWord(string word, int val, ref int previousVal) { cummulative += val; if (String.IsNullOrEmpty(word)) { if (isWord) { previousVal = wordVal; } isWord = true; wordVal = val; } else { if (!children.ContainsKey(word[0])) { children.Add(word[0], new PrefixSumTrie()); } PrefixSumTrie child = (PrefixSumTrie)children[word[0]]; child.AddWord(word.Substring(1), val, ref previousVal); } } private void RemoveWord(string word, int val) { if (cummulative > 0) { cummulative -= val; } if (!String.IsNullOrEmpty(word) && children.ContainsKey(word[0])) { ((PrefixSumTrie)children[word[0]]).RemoveWord(word.Substring(1), val); } } } }
Comments
Post a Comment