I user Trie to store the products. For every Trie node, it has the links to the next character and a PriorityQueue.
The PriorityQueue is used to store all products has has a prefix till the node's character.
After the Trie is build up, the searching will be very easy.
The Time Complexity:
Insert: O(n), n is the total number of characters in products.
Search: O(m*klog(k)), m is the length of SearchWord, k is the number of String in PriorityQueue.
Space Complexity: O(26*n) = O(n), n is the total number of characters in products.
class Solution { class Trie{ Trie[] next = new Trie[26]; PriorityQueue<String> products = new PriorityQueue<>(); public void insert(String s){ Trie t = this; for(char c: s.toCharArray()){ if(t.next[c-'a']==null) t.next[c-'a']= new Trie(); t = t.next[c-'a']; t.products.offer(s); } } public List<List<String>> search(String s){ List<List<String>> res = new ArrayList<>(); Trie t = this; for(char c: s.toCharArray()){ if(t!=null){ t = t.next[c-'a']; if(t!=null){ int size = Math.min(3, t.products.size()); List<String> list = new ArrayList<>(); for(int i=0;i<size;i++){ list.add(t.products.poll()); } res.add(list); }else{ res.add(new ArrayList<>()); } }else res.add(new ArrayList<>()); } return res; } } public List<List<String>> suggestedProducts(String[] products, String searchWord) { Trie t = new Trie(); for(String s: products){ t.insert(s); } return t.search(searchWord); } }