LeetCode642 Design Search Autocomplete System
classic Trie problem.

there are few points we should fully understand:
- return the top3 hottest sentence and sort them in order of hotter degree.
- if there’s less than 3, then return as many as possible.
- the problem did not explicit say that all the input sentence are unique
//of course we can solve this in hashmap and brute force.
//but remeber this. this is a string matching related problem, so we can use trie
//the solution is rewrite by leetcode but can't work, just can't figure out why
class AutocompleteSystem {
class Node { //we define this just because for the convinent of compare time and sentence
String sentence;
int times;
public Node(String st, int t) {
sentence = st;
times = t;
}
}
class Trie { //this is actually trieNode
int times; //if time is not 0, means we have a end of sentence here
Trie[] branches = new Trie[27]; //each trie is a list of trie, why do we have 27? because we have space char in there
}
private Trie root; //
private String cur_sent = ""; //the input of user current sent part of sentence
public AutocompleteSystem(String[] sentences, int[] times) {
root = new Trie(); //init
for (int i = 0; i < sentences.length; i++) {
insert(root, sentences[i], times[i]); //
}
}
private void insert(Trie t, String s, int times) { //build the trie
for (int i = 0; i < s.length(); i++) { //did we consider the space between words?
if (s.charAt(i) - 'a' >= 0) { //which mean current number is non-space(because the ASCII of space is way ahead of letters)
if (t.branches[s.charAt(i) - 'a'] == null) {
t.branches[s.charAt(i) - 'a'] = new Trie();
}
t = t.branches[s.charAt(i) - 'a'];
} else {
if (t.branches[26] == null) {
t.branches[26] = new Trie();
}
t = t.branches[26];
}
}
t.times += times;//when t reaches the bottom, we update the times of it, due to insert s might be duplicate, we have to += times
}
public List<String> input(char c) { //user input, one char each time
List<String> res = new ArrayList<>();
if (c == '#') { //means user input is finished,
insert(root, cur_sent, 1); //and we record this sentence in our trie as well
} else {
cur_sent += c; //current part of the sentence we have
List<Node> list = lookup(root, cur_sent); //get the search results in trie, we only look up based on user already inputted part, which is cur_sent
Collections.sort(list, (a, b) -> a.times == b.times? a.sentence.compareTo(b.sentence): b.times - a.times); //sort them according to the times attribute in nodes
//if list is less than length of 3 we will extract all, if longer, we will only extract 3 of them
for (int i = 0; i < list.size(); i++) {
if (i >= 3) {
break;
}
res.add(list.get(i).sentence);
}
}
return res;
}
private List<Node> lookup(Trie t, String s) { //look up s in trie t
List<Node> list = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) - 'a' >= 0) {
if (t.branches[s.charAt(i) - 'a'] == null) { //if any of the branches is null, means we dont have such prefix
return new ArrayList<>();
}
t = t.branches[s.charAt(i) - 'a'];
} else {
if (t.branches[26] == null) {
return new ArrayList<>();
}
t = t.branches[26];
}
}
//if we tranverse all, we have such prefix as string s in trie
traverse(s, t, list); //we will use this to get all the sentence that's with this prefix s
return list;
}
private void traverse(String s, Trie t, List<Node> list) { //use recursion to add elements in list
if (t.times > 0) { //when we hit a place where the node have
list.add(new Node(s, t.times)); //wrap the info as new Node, we don
}
for (char i = 'a'; i <= 'z'; i++) {
if (t.branches[i-'a'] != null) {
traverse(s + i, t.branches[i-'a'], list);
}
}
if (t.branches[26] != null) { //if index 26 is not a null, wich means
traverse(s+' ', t.branches[26], list);//
}
}
}
/**
* Your AutocompleteSystem object will be instantiated and called as such:
* AutocompleteSystem obj = new AutocompleteSystem(sentences, times);
* List<String> param_1 = obj.input(c);
*/
I rewrite and modify the code, it seem have no problems in logic, but it just can’t pass all tests.
the general idea for this problem is comlicated:
- we are gonna use trie to solve this problem. we use given sentence and time to construct a trie
- so first, in order to better compare what is the hottest and what is the smallest in lexicographic order, we create a class called node, which have sentence and times two attribute.
- and since we need use trie, then we create a class called trieNode
- Now, for the constructor of this whole class we are gonna to implement, we are gonna to construct the whole trie using sentence privded one by one. and we are gonna to write a method called insert.
- now we are gonna to implement the input method, in order to keep track of the user input, we will use a global varibale cur_sent to record user input before “#”. and in this method, we look up in the trie each time user input a char(this cur char and previous combined as a partial sentence and we look that up in trie)
- so now we are gonna to implement the lookup method to find user input in trie. and we need to return all the sentence in trie with the same prefix, so after we reached the end of user input, we need to use dfs to tranverse the remaining path, so next we are gonna to implement the tranverse method.
- we use dfs to implement the tranverse() method.

浙公网安备 33010602011771号