Showing posts sorted by relevance for query trie. Sort by date Show all posts
Showing posts sorted by relevance for query trie. Sort by date Show all posts

Monday, June 15, 2020

Leetcode discuss: 212. Word Search II

Here is my post.

C# Trie data structure DFS algorithm practice in June 2020

June 15, 2020

Trie is a most important data structure to expedite search prefix is in the dictionary of words. I like to build a class TrieNode and also put together a Trie showcase for my past practice.

Case study

Problem statement:
Given a matrix of chars, and also a list of words as dictionry, ask to find all words in the matrix which are in given words.

Challenges:

  1. Build a Trie class
  2. Backtracking using depth first search
  3. Mark visited to avoid a char used twice in mutiple words
  4. Work on a test case to make a Trie class easy to write.

Space complexity
Use existing matrix to mark visited, backtracking if the word is not found. Extra space is not needed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _212_word_search_II
{
    class Program
    {
        static void Main(string[] args)
        {
        }

        /// <summary>
        /// June 15, 2020
        /// class TrieNode
        /// API: 
        /// BuildTrie 
        /// IsWord
        /// DeDuplicate
        /// </summary>
        public class TrieNode
        {
            public TrieNode[] Next = new TrieNode[26];
            public String Word { get; set; }  // it is word, a string from root node to current char

            /// <summary>
            /// code review 
            /// </summary>
            /// <param name="words"></param>
            /// <returns></returns>
            public TrieNode Build(String[] words)
            {
                TrieNode root = new TrieNode();

                foreach (var word in words)
                {
                    var trie = root;
                    foreach (var c in word.ToCharArray())
                    {
                        int current = c - 'a';

                        if (trie.Next[current] == null)
                        {
                            trie.Next[current] = new TrieNode();
                        }

                        trie = trie.Next[current]; // iterate to next 
                    }

                    // reach the leaf node of trie - add word string
                    trie.Word = word;
                }

                return root;
            }

            public bool IsWord()
            {
                return Word != null; 
            }

            /// <summary>
            /// To avoid a word to be added more than once 
            /// </summary>
            public void DeDuplicate()
            {
                Word = null; 
            }
        }

        /// <summary>
        /// code review on June 15, 2020
        /// The idea is to start from each char in the matrix to apply depth first search, backtracking is needed to 
        /// reduce the space complexity, and also Trie is used to build from dictionary to make it more efficient to search 
        /// if the prefix is in the dictionary. 
        /// </summary>
        /// <param name="board"></param>
        /// <param name="words"></param>
        /// <returns></returns>
        public IList<string> FindWords(char[][] board, string[] words)
        {
            var set = new HashSet<string>();
            var trie = new TrieNode();

            var root = trie.Build(words); ;

            for (int row = 0; row < board.Length; row++)
            {
                for (int col = 0; col < board[0].Length; col++)
                {
                    applyDFS(board, row, col, root, set);
                }
            }

            return set.ToList();
        }

        /// <summary>
        /// Depth first search algorithm
        /// Design concern: apply backtracking to save space - using existing matrix to mark '#' as visited
        /// </summary>
        /// <param name="board"></param>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <param name="trie"></param>
        /// <param name="found"></param>
        private static void applyDFS(char[][] board, int row, int column, TrieNode trie, HashSet<String> found)
        {
            // current char to visit           
            var visit = board[row][column];

            // skip visited ones
            if (visit == '#' || trie.Next[visit - 'a'] == null)
            {
                return;
            }

            trie = trie.Next[visit - 'a'];

            if (trie.IsWord())  // the word is found, need to add to result 
            {
                found.Add(trie.Word);                
            }

            // mark visited
            board[row][column] = '#'; // mark the node value with '#', so it will not match any char

            // up, left, down, right four directions
            var rows = board.Length;
            var columns = board[0].Length;

            if (row > 0)
            {
                applyDFS(board, row - 1, column, trie, found);
            }

            if (column > 0)
            {
                applyDFS(board, row, column - 1, trie, found);
            }

            if (row < rows - 1)
            {
                applyDFS(board, row + 1, column, trie, found);
            }

            if (column < columns - 1)
            {
                applyDFS(board, row, column + 1, trie, found);
            }

            // depth first search - backtracking 
            board[row][column] = visit; 
        }        
    }
}


Monday, July 24, 2017

Boggle - find words in matrix of letters

July 24, 2017

Plan to study the algorithm Boggle coding blog. The blog link is here written by Aviad Ezra.

There are a lot of thing for Julia to learn through those blog and code sample. Let us read words from Aviad Ezra together in the following:

Learn: Cracking the interview, solve all 189 questions.

Practice: Nothing beats mock interviews. It will boost your confidence and you’ll learn a ton from having someone watching you and listening to your explanations while you solve coding problems. You can pair with a friend or use one of the free peer-to-peer mock interviewing platforms. You don’t need to sacrifice your first interviews just to get hands-on practice.

Think fast: Developers that can think on their feet do much better in coding interviews. Practice in as many competitive programming sessions as you can.

Before you lost hope, keep in mind that there's a finite number of algorithms topics and only a handful of data structures that are used in the interviews.

Those words from  Aviad Ezra are so encouraging, Julia wrote her own blog about "Can mocking make difference?". First time she learns to work with people, share with people, learn from people on small things, like presenting her face in the centre through the video, ask good questions, give good hint, form a quick friendship etc.

In the following, Julia uses Leetcode 212 to help herself review Trie data structure and learn how to apply same algorithm as Boggle classified in Leetcode.



Leetcode 212 - word search II


Review Leetcode 212 last practice using Trie. The link is here.

It is so surprising that learning Trie and practice depth first search is most fun activities in the summer of 2017. Julia has to warm up the algorithm, play with one test case with Trie class, and also make the code more readable. Here is the warmup C# code using Trie data structure, recursive function calls. The solution is optimal and also pass online judge.

It is also a good idea to discuss why Trie is needed for better time complexity.

Brute force solution is to go over each word in the dictionary, and then try to find it in the matrix. The total number of search using DFS is m (words) * rows (matrix) * columns (matrix).

The brute force solution has timeout issue through Leetcode online judge. We like to review why the time complexity should be better.

Let us go over dictionary with 4 words, "aaa", "aaaa","aaab", "aaac". If we pre-process the dictionary and store all words in a Trie, and then we do not have to go over each words to search matrix. We only need to go over each element in matrix as start char in a word, search the trie to find match words using recursive function. The number of search using DFS is rows (matrix) * columns (matrix).

Second advantage related to the above 4 words ( "aaa", "aaaa","aaab", "aaac") is taking advantage of Trie data structure. The space complexity of Trie is better compared to hashset or hashtable. The same prefix "aaa" is only repeated once in the Trie.

This hard level algorithm applying Trie will be Julia's most favorite algorithm in the month of July 2017.

One of practice in 2017 is prefix neighbor on hackerrank, Julia asked the code review on stackexchange.com.


July 26, 2017

Trie against Hashset


Related to the test with a dictionary "aaa","aaaa","aaab","aaac","aaad", let us work together to talk about the difference.

For example, if the dictionary is saved in hashset, then go over each word in the dictionary, try to find word in matrix.
For example, "aaab", the first three letters has to be compared and they are the same first, then the last letter will be checked. Same will be applied to another 4 words. In total, the prefix "aaa" will be compared exactly 5 times in order to find those 5 words.

Can we do better? Just compare the prefix "aaa" once? Cetainly we can. We can save the words in a trie instead of hashset.

a
|
a
|
a
|\  \  \
| \  \  \
|  \  \  \
a  b  c  d



Trie efficiency talk 



It takes some time to get comfortable to design a Trie. So far, Julia has written a Trie implementation more than 4 times in C# last 3 years. Given the fact that she has worked on computer science more than 20 years, if she writes a algorithm every day, then she will write 60,000 algorithms. It is smart to focus on one simple thing, write code for algorithm and data structure, no matter life goes up and down, make it a hobby.

How to design a Trie so that the space complexity is minimum?
For example, the dictionary has the following words, "aaa","aaaa","aaaaa","aaaaaa".
How to store them in Trie efficiently?
a
|
a
|
a   word: "aaa"
|
a   word: "aaaa"
|
a   word: "aaaaa"
|
a   word: "aaaaaa"

The above diagram shows that those four words are saved in a Trie. How many char 'a' are saved in Trie, only 6, not 3 + 4 + 5 + 6 = 18 chars. Four words are saved along the trie nodes.

Every node can represent a word, it does not have to be a leaf node.

It is a smart decision to write down some test cases, so next time when Julia comes cross an algorithm, she can quickly relate to the test cases and figure out the advantage of using Trie.

Tuesday, June 13, 2017

Leetcode 212: Word Search II

June 13, 2017

Problem statement

Introduction



Trie is the kind of tree data structure and easy to save space with common prefix. Julia spent over 5 hours to work on one of trie algorithm and posted a code review on stackexchange.com called prefix neighbor. She went through the trie and learned that the trie can be in any form.

This time Julia had to relearn trie again. She had the weakness of data structure Trie, she could not figure out how to solve test case 36 and 37 two test cases timeout issue.

Code practice 


It is the hard level algorithm.

Julia worked on the Leetcode 212 word search.

Her first submission failed last 2 test cases from 36 - 37. Timeout issue. Julia did not know that she needs to use trie, she just used recursive function. The code is here.

Here is the C# code.

She studies the discussion written by a Googler - Yavinci, and wrote second practice. Still work on the code for more testing. Here is the C# code.

Julia continued to work on the trie and here is the C# code passing leetcode online judge.


Algorithm talk - learn Trie again



It is interesting to learn how data structure Trie to help solving timeout issues. For example, there are a lot of words like "aaaa", "aaab", "aaac", ...,"aaaz", Julia was so naive on June 13, 2017. She just goes over each word in the dictionary, and try to find each word using depth first search (DFS) recursive calls.

However the last 2 test case of 37 test cases time out. But Julia did not have idea how to solve it.

Julia needs to take a data structure coaching lesson again. so great to catch the opportunity.

As we can see, those words have same prefix "aaa", and the fourth char or last char is a to z. How to save the time to search, for example, if the path is the prefix of one word, then we need to continue to search.

Think about time complexity. My original solution (the C# code) is to go over each word, and then start to search board using DFS; so time complexity is related to how many words, each word is searched through board using DFS. If 26 words all starting from same prefix "aaa", then "aaa" will be searched in the board over 26 times.

The idea of using Trie, and then go over each element in the board, and then do DFS search against the Trie tree.

So preparation is the key, store all words to a prefix tree first.

Trie 


Plan to read Trie wiki article, review time complexity advantage of using Trie data strucutre.

A trie has a number of advantages over binary search tree. A trie can also be used to replace a hash table.

Topcoder using Trie - the article link is here.
Hackerearth tutorial about Trie - the article link is here.
Read 10 pages lecture notes about Trie - CMU lecture notes is here.

Wednesday, June 24, 2020

Leetcode discuss: 208. Implement Trie (Prefix Tree)

Here is the post.

C# Trie algorithm practice in June 2020

June 24, 2020
Introduction
It is the second algorithm of my mock interview. I did not start to work on until 20 minutes left. So I did successfully submit the answer, since I just worked on Trie algorithm hard level 212 Word search. I also wrote in detail how to design a Trie. The link will be provided here as well.
Here are my practice:
  1. Understand Trie recursive data structure of Tree;
  2. Think about Trie as a binary tree when I implement, and then understand "new Trie()" for child node assignment;
  3. Do not get confused with statement "root.word != null", another one is "word != null"
public class Trie {

    
    private Trie[] Children = new Trie[26];
    private string word; 
    
    /** Initialize your data structure here. */
    public Trie() {
        //Children = new Trie[26];
        
    }
    
    /** Inserts a word into the trie. */
    public void Insert(string word) {
        if(word == null || word.Length == 0)
            return;
        
        var root = this; 
        
        foreach(var item in word)
        {
            if(root.Children[item - 'a'] == null)
            {
                root.Children[item - 'a'] = new Trie();
            }
            
            root = root.Children[item - 'a'];
        }
        
        root.word = word;  
    }
    
    /** Returns if the word is in the trie. */
    public bool Search(string word) {
        if(word == null || word.Length == 0)
            return false;
        
        var root = this; 
        
        foreach(var item in word)
        {
            if(root.Children[item - 'a'] == null)
            {
                return false;
            }
            
            root = root.Children[item - 'a'];
        }
        
        return root.word != null; 
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public bool StartsWith(string prefix) {
        if(prefix == null || prefix.Length == 0)
            return false;
        
        var root = this; 
        
        foreach(var item in prefix)
        {
            if(root.Children[item - 'a'] == null)
            {
                return false;
            }
            
            root = root.Children[item - 'a'];
        }
        
        return true; 
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.Insert(word);
 * bool param_2 = obj.Search(word);
 * bool param_3 = obj.StartsWith(prefix);
 */


Tuesday, June 16, 2020

Leetcode discuss: 212. Word Search II

Here is the link. 

C# Trie design challenge and DFS algorithm practice in June 2018

June 16, 2020
It is challenge task to write the depth first search algorithm using Trie data structure. It took me several hours to make it work. I failed three test cases, and then I like to write down my lessons here.

First it is the design of depth first search. The checking of our-of-index-range of the matrix, visited node, child node is not in Trie data structure object are those three important checkings for a complete test.

Second one is to understand Trie data structure. Trie is a recursive data structure, so it is important to identify current node matrix[row][col] with function argument TrieNode parentNode relationship. The design is to pass parentNode which is not null, so the child node may not be in Trie data structure object.

Third one is to write TrieNode Build function to construct a Trie tree object. It is not easy task, so please work on "a", one char word, and it should be two level, parent node is dummy head, and dummy head's child is 'a' instead.

What else can I write down to make this TrieNode class crafting more error-prone?

  1. I change for(int i = 0; i < words.Length; i++) to foreach loop to make code clean, no need to use i to do any checking.
  2. Dummy head is important, and also understand that the call is passed using parent node;
  3. Statement: public TrieNode[] nodes = new TrieNode[26]; each nodes[i] is still null pointer.
  4. Remove "iterate.word = word;" outside statement "foreach (char c in word)" in TrieNode class API defintion.
  5. GetByIndex API of TrieNode should check pointer null first.

Template of DFS

  1. Design a DFS function to search a matrix, please understand DFS and also backtracking.
  2. Function name runDFS is good enough, TrieNode parentNode argument should be clearly defined, since current char may not be in Trie object.
  3. Put all edge cases in one statement, do not define explanation variable "var visit = board[row][col]" before checking index range and also board's content has not been visited yet.
  4. One word in dictionary can be a prefix in another word in dictionary, so it should continue to search. Termination should not put after the word is added to found string.
  5. Think about time complexity using Trie compared to HashSet, and practice more often Trie to solve problems.
  6. Discuss termination of DFS with interviewer or think about more test cases. It is safe to continue to search if a word is found, let it fall through the checking of index-out-range or char is not in the tree.

Template of TrieNode definition of Build

  1. Trie is a recursive data structure, tree data structure;
  2. Trie should start from a dummy hand for easy reference;
  3. Child node is one of element of TrieNode[26] array
  4. Child node is still null pointer even TrieNode[26] is called using statement " ... = new TrieNode();"
  5. Clean up TrieNode Build API

Special case: binary tree
To expedite the process to craft a TrieNode class Build API, treat special case a binary tree and see how to make it work; left and right child map to index 0 and 1. If left child exist, then do nothing except going to left child for next iteration. If left child does not exist, then create one first. Go over each word in dictionary, build a binary tree to include all words, assuming that all chars are 'a' or 'b' in those words. Try to go over the following test case 3, build a trie by hand first, and then talk about how to write a trie version with size of 26 array.

For each word in dictionary, go through char by char, and then start from dummy head of Trie object, and then if child node is created then continue, otherwise create the tree object.

Test case Trie
I failed the test case 3, so I like to share this test case.

image

One word in dictionary can be a prefix in another word in dictionary, so it should continue to search. Depth first search algorithm's termination should not put after the word is added to found string.
In the above test case, "aaa" is the prefix of "aaaa".

Practice talk
I could not perform very well on Amazon code screen this March. The reason is that debugger is disabled, and my design is not relax to allow mistake happen. I write something to remind myself, focus on design when debugging, think about modifying design to make it more robust.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _212_word_search_warmup_June_16_20
{
    class Program
    {
        static void Main(string[] args)
        {
            //RunTestcase1();
            //RunTestcase2();
            RunTestcase3(); 
        }

        public static void RunTestcase1()
        {
            var board = new char[4][];

            board[0] = "oaan".ToCharArray();
            board[1] = "etae".ToCharArray();
            board[2] = "ihkr".ToCharArray();
            board[3] = "iflv".ToCharArray();

            var found = FindWords(board, new string[] { "oath", "pea", "eat", "rain" }); 
        }

        public static void RunTestcase2()
        {
            var board = new char[1][];

            board[0] = "a".ToCharArray();            

            var found = FindWords(board, new string[] { "b"}); 
        }


        public static void RunTestcase3()
        {
            //[["a","b"],["a","a"]]
            // ["aba","baa","bab","aaab","aaa","aaaa","aaba"]
            var board = new char[2][];

            board[0] = "ab".ToCharArray();
            board[1] = "aa".ToCharArray();

            var found = FindWords(board, new string[] { "aba", "baa", "bab", "aaab", "aaa", "aaaa", "aaba" });

            // ["aba","aaa","baa","aaba"]
            // ["aaa","aaab","aaba","aba","baa"]  expected - mine is missing: "aaab"
        }

        /// <summary>
        /// design Trie class 
        /// </summary>
        class TrieNode
        {
            public TrieNode[] nodes = new TrieNode[26];
            private string word;

            /// <summary>
            /// Design Trie class
            /// Please use the following test cases:
            /// ["a"]
            /// </summary>
            /// <param name="words"></param>
            /// <returns></returns>
            public TrieNode Build(string[] words)
            {
                if (words == null)
                {
                    return new TrieNode(); 
                }

                var original = new TrieNode(); // dummy head                
                
                var length = words.Length;   // ["oath",""]
                foreach (var word in words)
                {
                    var iterate = original;  // start from root char again                    

                    foreach (char c in word)
                    {                                                                       
                        int index = c - 'a';
                        if (iterate.nodes[index] == null)  // caught by online judge
                        {
                            iterate.nodes[index] = new TrieNode();
                        }

                        // go to next trie node  
                        iterate = iterate.nodes[index];                        
                    }

                    iterate.word = word;
                }

                return original; 
            }

            public bool IsWord()
            {
                return word != null;
            }

            public string GetWord()
            {
                return word; 
            }

            public bool IsUnitialized()
            {
                return nodes == null; 
            }

            public void Initialize()
            {
                nodes = new TrieNode[26];
            }

            public TrieNode GetByIndex(int index)
            {
                if (nodes[index] == null)
                    return null;

                return nodes[index];
            }
        }

        /// <summary>
        /// Code review on June 16, 2020
        /// warmup practice
        /// 1. Design backtracking, walk through the example "oath" to explain to myself 
        /// how 'o','a','t','h' is marked as '#', after the word "oath" is added to the hashset, 
        /// all matrix's positions have original chars back. 
        /// 2. I did not fully understand how to apply backtracking back in June 2019, so I wrote my experience
        /// on Lowest common ancestor showcase on Leetocode discuss
        /// 3. This is perfect time for me to master the backtracking in DFS. 
        /// Facts:
        /// Sometimes one word is another word's prefix in dictionary. 
        /// So do not stop search if the word is added to found hashset. 
        /// </summary>
        /// <param name="board"></param>
        /// <param name="words"></param>
        /// <returns></returns>
        public static IList<string> FindWords(char[][] board, string[] words)
        {
            if (board == null || words == null)
            {
                return new List<string>(); 
            }

            // build a trie
            var trie = new TrieNode(); 
            trie = trie.Build(words);  // caught by debugger            

            var rows = board.Length;
            var columns = board[0].Length;

            var set = new HashSet<string>(); 

            for (int row = 0; row < rows; row++)
            {
                for (int col = 0; col < columns; col++)
                {
                    runDFS(board, row, col, trie, set);
                }
            }

            return set.ToList(); 
        }

        /// <summary>
        /// Design requirement: 
        /// TrieNode
        /// Make sure that parentNode is not null all the time
        /// current node is one of parentNode's child
        /// </summary>
        /// <param name="board"></param>
        /// <param name="words"></param>
        /// <param name="found"></param>
        private static void runDFS(char[][] board, int row, int col, TrieNode parentNode, HashSet<string> found)
        {
            var rows = board.Length;
            var columns = board[0].Length;
            var visitedChar = '#';            

            // out of range or visited already
            // or current node trie[visit - 'a'] is not in Trie
            if (row < 0 || row >= rows || col < 0 || col >= columns || 
                board[row][col] == visitedChar ||
                parentNode.GetByIndex(board[row][col]-'a') == null
                )  
            {
                return; 
            }

            var visit = board[row][col];
            var child = parentNode.GetByIndex(board[row][col] - 'a');

            // work on trie
            if (child.IsWord())
            {
                found.Add(child.GetWord());
                //return;  // June 16, 2020 case 3: sometimes a word is another word's prefix in dictionary. So continue to search. 
            }

            // Design DFS with backtracking 
            var current = board[row][col];
           
            // mark visited
            board[row][col] = visitedChar;            
            
            // Four directions - clockwise, top, right, down, left
            runDFS(board, row - 1, col, child, found);
            runDFS(board, row, col + 1, child, found);
            runDFS(board, row + 1, col, child, found);
            runDFS(board, row, col - 1, child, found);

            //backtracking
            board[row][col] = current; 
        }
    }
}

Comment

Wednesday, September 7, 2016

Longest Common Prefix - using Trie

Sept. 7, 2016

Work on C# practice:
http://www.geeksforgeeks.org/longest-common-prefix-set-5-using-trie/

One of longest common prefix series:
1. http://www.geeksforgeeks.org/longest-common-prefix-set-1-word-by-word-matching/
2. http://www.geeksforgeeks.org/longest-common-prefix-set-2-character-by-character-matching/
3. http://www.geeksforgeeks.org/longest-common-prefix-set-3-divide-and-conquer/
4. http://www.geeksforgeeks.org/longest-common-prefix-set-4-binary-search/
5. http://www.geeksforgeeks.org/longest-common-prefix-set-5-using-trie/

Will work on coding very soon.

C# practice:
https://gist.github.com/jianminchen/d65887908a16e1c12d708a2912c4c081

Add time complexity and auxiliary space detail:
Time Complexity : Inserting all the words in the trie takes O(MN) time and performing a walk on the trie takes O(M) time, where-
N = Number of strings
M = Length of the largest string string
Auxiliary Space: To store all the strings we need to allocate O(26MN) ~ O(MN) space for the Trie.
From the website:

Editorial Notes:
1. This is the first C# implementation of Trie Julia wrote.

2. How does she get here?
HackerRank code sprint #6 has an algorithm related to suffix array ->
continue to work on suffix array ->
Longest common prefix ->
string search speed up ->
found a 5 solution series on geeksforgeeks ->
work on 5th solution, Trie, LCP

3. Prior experience worked on suffix array:
http://juliachencoding.blogspot.ca/2016/04/april-11-2016-plan-to-work-on-lcp-array.html
http://juliachencoding.blogspot.ca/2016/04/april-11-2016-plan-to-work-on-lcp-array.html

Try to solve the advanced problem again after 5 month (April, 2016) using suffix array, LCP, two pointer technique:
https://www.hackerrank.com/challenges/string-function-calculation




Wednesday, May 23, 2018

Being an interviewee: Suggest a char with maximum occurrence at the position with the given prefix

May 23, 2018

Introduction


It is my most favorite algorithm to practice with my coach. The algorithm is called to suggest a char with maximum occurrence at the position with the given prefix.

The coached asked me if I have Trie experience two days before my mock interview, so I spent some time to review Leetcode 212 and also my question on stackexchange.com.

The conversation of writing a Trie data structure was very interesting.


Coach: can you explain how you define the Trie?
Julia: It should be recursive structure, Children should have Node type as well.
Coach: Do you need to have a list of numbers for children?
Julia: No. It should be minimum. Every node just takes care of its own number.

In-between the mock interview, the coach asked me why you define the Trie this way, save "ABC" as a member of class definition. I just told the coach that I memorized the solution I reviewed recently. But actually we do not need to do that here. I felt much more relax after we work together more than 10 hours.

Trie algorithm


I learn how to work with the coach and write a solution in the mock interview. And also the coach asked me to test the code using the test case documented from line 93 to line 96, I found the bug on line 107, and delay increment of index variable until line 123.

Here is the transcript of the mock interview.

Follow up 


I wrote the C# code and tested it using a simple test case. Now it is 12:21 AM, I need to rush to go to bed since at tomorrow 8:00 AM I will have a mock interview.

10:00 PM mock interview as interviewer


I also ask the interviewee to work on the algorithm at 10:00 PM mock interview. The intervewee has more than eight years experience working in Silicon Valley to target for biggest software companies, and I helped him to write a Trie solution. What I did is to try to copy my coach, how he did to me. I asked the interviewee to work on the test case, show me the trie, and also give hint to use array for fixed size instead of using Dictionary.

Here is the C# code the interviewee wrote before I write my own C# solution.

Code review from my coach


I sent an email to ask the coach to review my code before I will have next mock interview. The coach offered me to send the code before mocking interview after our second mock interview, so he can prepare better for next mock interview. We can squeeze in more activities in the mock interview together. My coach is super talent programmer and I like his working attitude.

"I think that it is definitely no problem at all. Let us meet Friday morning.

I just like to send you the code I wrote for suggest char based on prefix.

Here is the link."

May 25, 2018
8:00 AM

My coach told me that one thing is not correct. The iterate variable may be null pointer. I need to add null pointer checking on line 152.