Design Search Autocomplete System

Design a search autocomplete system for a search engine. Users may input a sentence (at least one word and end with a special character '#'). For each character they type except '#', you need to return the top 3 historical hot sentences that have prefix the same as the part of sentence already typed. Here are the specific rules:

  1. The hot degree for a sentence is defined as the number of times a user typed the exactly same sentence before.
  2. The returned top 3 hot sentences should be sorted by hot degree (The first is the hottest one). If several sentences have the same degree of hot, you need to use ASCII-code order (smaller one appears first).
  3. If less than 3 hot sentences exist, then just return as many as you can.
  4. When the input is a special character, it means the sentence ends, and in this case, you need to return an empty list.

Your job is to implement the following functions:

The constructor function:

AutocompleteSystem(String[] sentences, int[] times): This is the constructor. The input is historical dataSentences is a string array consists of previously typed sentences. Times is the corresponding times a sentence has been typed. Your system should record these historical data.

Now, the user wants to input a new sentence. The following function will provide the next character the user types:

List<String> input(char c): The input c is the next character typed by the user. The character will only be lower-case letters ('a' to 'z'), blank space (' ') or a special character ('#'). Also, the previously typed sentence should be recorded in your system. The output will be the top 3 historical hot sentences that have prefix the same as the part of sentence already typed.

Example:
Operation: AutocompleteSystem(["i love you", "island","ironman", "i love leetcode"], [5,3,2,2])
The system have already tracked down the following sentences and their corresponding times:
"i love you" : 5 times
"island" : 3 times
"ironman" : 2 times
"i love leetcode" : 2 times
Now, the user begins another search:

Operation: input('i')
Output: ["i love you", "island","i love leetcode"]
Explanation:
There are four sentences that have prefix "i". Among them, "ironman" and "i love leetcode" have same hot degree. Since ' ' has ASCII code 32 and 'r' has ASCII code 114, "i love leetcode" should be in front of "ironman". Also we only need to output top 3 hot sentences, so "ironman" will be ignored.

思路:这题跟 Search Suggestion System一模一样,细微的差别是input type完了之后,输入的那个词,也要进入词频统计,那么trienode里面需要存sentence的frequency,另外注意的地方是:type的时候,如果是null了,那么以后的cur也是null,

class AutocompleteSystem {
    private class TrieNode {
        public HashMap<Character, TrieNode> children;
        public HashMap<String, Integer> counts;
        public boolean isword;
        public TrieNode() {
            this.children = new HashMap<Character, TrieNode>();
            this.counts = new HashMap<String, Integer>();
            this.isword = false;
        }
    }
    
    private class Trie {
        private TrieNode root;
        
        public Trie() {
            this.root = new TrieNode();
        }
        
        public void insert(String sentence, int time) {
            TrieNode cur = root;
            for(char c : sentence.toCharArray()) {
                TrieNode next = cur.children.get(c);
                if(next == null) {
                    next = new TrieNode();
                    cur.children.put(c, next);
                }
                cur = next;
                cur.counts.put(sentence, cur.counts.getOrDefault(sentence, 0) + time);
            }
            cur.isword = true;
        }
    }
    
    private class Node {
        private String sentence;
        private int fre;
        public Node(String sentence, int fre) {
            this.sentence = sentence;
            this.fre = fre;
        }
    }
    
    private class NodeComparator implements Comparator<Node> {
        @Override
        public int compare(Node a, Node b) {
            if(a.fre != b.fre) {
                return b.fre - a.fre;
            } else {
                return a.sentence.compareTo(b.sentence);
            }
        }
    }

    private Trie trie;
    private StringBuilder sb;
    private TrieNode cur;
    private String prefix;
    public AutocompleteSystem(String[] sentences, int[] times) {
        trie  = new Trie();
        for(int i = 0; i < sentences.length; i++) {
            trie.insert(sentences[i], times[i]);
        }
        prefix = "";
        sb = new StringBuilder();
        cur = trie.root;
    }
    
    public List<String> input(char c) {
        if(c == '#') {
            trie.insert(sb.toString(), 1);
            sb = new StringBuilder();
            cur = trie.root;
            return new ArrayList<String>();
        }
        sb.append(c);
        // 注意这里,如果下面没有了,那么以后也没有了,cur 赋值为null;
        if(cur == null || !cur.children.containsKey(c)) {
            cur = null;
            return new ArrayList<String>();
        } else {
            cur = cur.children.get(c);
            PriorityQueue<Node> pq = new PriorityQueue<Node>(new NodeComparator());
            for(String sentence: cur.counts.keySet()) {
                pq.add(new Node(sentence, cur.counts.get(sentence)));
            }
            List<String> list = new ArrayList<String>();
            int count = 0;
            while(!pq.isEmpty() && count < 3) {
                Node node = pq.poll();
                list.add(node.sentence);
                count++;
            }
            return list;
        }
    }
}

/**
 * Your AutocompleteSystem object will be instantiated and called as such:
 * AutocompleteSystem obj = new AutocompleteSystem(sentences, times);
 * List<String> param_1 = obj.input(c);
 */
发布了710 篇原创文章 · 获赞 13 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/u013325815/article/details/105489360
今日推荐