Projete um sistema de preenchimento automático de pesquisa para um mecanismo de pesquisa. Os usuários podem inserir uma frase (pelo menos uma palavra e terminar com um caractere especial '#'
). Para cada caractere digitado, exceto '#' , é necessário retornar as três principais frases históricas importantes com o prefixo igual à parte da frase já digitada. Aqui estão as regras específicas:
- O grau quente de uma frase é definido como o número de vezes que um usuário digitou exatamente a mesma frase antes.
- As três principais frases quentes retornadas devem ser classificadas por grau quente (a primeira é a mais quente). Se várias frases tiverem o mesmo grau de calor, você precisará usar a ordem do código ASCII (a menor aparecerá primeiro).
- Se houver menos de três frases quentes, retorne o máximo que puder.
- Quando a entrada é um caractere especial, significa que a frase termina e, nesse caso, você precisa retornar uma lista vazia.
Seu trabalho é implementar as seguintes funções:
A função construtora:
AutocompleteSystem(String[] sentences, int[] times):
Este é o construtor. A entrada são dados históricos . Sentences
é uma matriz de cadeias de caracteres que consiste em frases digitadas anteriormente. Times
é o horário correspondente em que uma frase foi digitada. Seu sistema deve registrar esses dados históricos.
Agora, o usuário deseja inserir uma nova frase. A função a seguir fornecerá o próximo caractere digitado pelo usuário:
List<String> input(char c):
A entrada c
é o próximo caractere digitado pelo usuário. O caractere será apenas letras minúsculas ( 'a'
para 'z'
), espaço em branco ( ' '
) ou um caractere especial ( '#'
). Além disso, a frase digitada anteriormente deve ser gravada no seu sistema. A saída será as três principais frases quentes históricas que têm o prefixo igual à parte da frase já digitada.
Exemplo:
Operação: AutocompleteSystem (["eu te amo", "ilha", "homem de ferro", "eu amo código leet"], [5,3,2,2])
O sistema já rastreou as seguintes frases e suas correspondências vezes: "i love you"
: 5
tempos "island"
: 3
tempos "ironman"
: 2
tempos "i love leetcode"
: 2
tempos
agora, o usuário começa outra pesquisa:
Operation: entrada ( 'i')
saída: [ "eu te amo", "ilha", "eu amo leetcode"]
Explicação:
Existem quatro frases com prefixo "i"
. Entre eles, "ironman" e "eu amo leetcode" têm o mesmo grau quente. Como ' '
possui o código ASCII 32 e 'r'
possui o código ASCII 114, "eu amo leetcode" deve estar na frente de "ironman". Também precisamos apenas emitir as três principais frases quentes, para que "ironman" seja ignorado.
Ideia: Essa pergunta é exatamente a mesma do Sistema de Sugestões de Pesquisa . A diferença sutil é que, após o término do tipo de entrada, a entrada de palavras também deve inserir as estatísticas de frequência da palavra. Em seguida, a frequência da sentença precisa ser armazenada no trienode. É nulo, então o futuro cur também é nulo,
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);
*/