leetcode:642.设计搜索自动补全系统

题目来源

题目描述

在这里插入图片描述

题目解析

根据题意:

  • 补全的句子是按照之前出现的频率排列的,高频率的在最上面
  • 如果频率相同,就按照字母顺序来显示

规则:

  • 每输入一个字符,就返回自动补全的句子
  • 如果遇到#,表示完整句子结束

分析:

  • 因为需要记住频率,那么就肯定需要一个hashmap,建立句子和其出现频率的映射
  • 还需要一个字符串 data,用来保存之前输入过的字符

在构造函数 AutocompleteSystem(vector<string> sentences, vector<int> times)

  • 参数是:历史输入的句子和句子历史输入的次数
  • 因此:需要将其加入hashmap,然后data初始化为空字符串

vector<string> input(char c)函数中:

  • 先判断输入字符是否为#
    • 如果是的话,那么就表示当前的data字符串已经是一个完成的句子了,在hashmap中次数加1,并且data清空,返回空集
    • 如果不是的话,将当前字符加入data字符串中,然后去找包含data前缀的前三高频句子。
  • 关于:找包含data前缀的前三高频句子?遍历 hashmap ,
    • 先看前缀是否匹配,如果匹配,那么将这个 pair 加入优先队列中
      • 怎么验证当前 data 字符串是否是其前缀呢?没啥好的方法,只能逐个字符比较
    • 要找前三高频句子,可以使用优先队列来做,
      • 优先队列设计思路是:
        • 始终用优先队列保存频率最高的三个句子
        • 应该把频率低的后缀字母顺序大的放在队首,以便随时可以移出队列,所以应该是个最小堆,队列元素是pair<句子,句子的频率>,并且根据其频率大小进行排序,要重写优先队列的 comparator。
      • 如何保持保存频率最高的三个句子?
        • 将pair加入优先队列之后,如果发现此时队列中的元素大于三个,那把队首元素移除,因为是最小堆,所以频率小的句子会被先移除
  • 怎么返回结果?优先队列保存着频率最高的三个数字,频率低的在最前面,所以先先出队列的是频率小的句子,所以要加到结果 res 的末尾
class AutocompleteSystem {
public:
    AutocompleteSystem(vector<string> sentences, vector<int> times) {
        for (int i = 0; i < sentences.size(); ++i) {
            freq[sentences[i]] += times[i]; 
        }
        data = "";
    }    
    vector<string> input(char c) {
        if (c == '#') {
            ++freq[data];
            data = "";
            return {};
        }
        data.push_back(c);
        auto cmp = [](pair<string, int>& a, pair<string, int>& b) {
            return a.second > b.second || (a.second == b.second && a.first < b.first);
        };
        priority_queue<pair<string, int>, vector<pair<string, int>>, decltype(cmp) > q(cmp);
        for (auto f : freq) {
            bool matched = true;
            for (int i = 0; i < data.size(); ++i) {
                if (data[i] != f.first[i]) {
                    matched = false;
                    break;
                }
            }
            if (matched) {
                q.push(f);
                if (q.size() > 3) q.pop();
            }
        }
        vector<string> res(q.size());
        for (int i = q.size() - 1; i >= 0; --i) {
            res[i] = q.top().first; q.pop();
        }
        return res;
    }
    
private:
    unordered_map<string, int> freq;
    string data;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值