LeetCode692.前K个高频单词
原题链接:前K个高频单词

1. 需要了解的知识点

数据结构

unordered_map: 哈希函数组成的 无序 map。(此题unordered_map无序比有序map效率更高)
multimap: 可重复的map

相关函数API

vector<int>

empty():      判断Vector是否为空
size():          返回Vector元素数量的大小
rbegin(),rend():   反向迭代器
clear():           清空所有元素
sort():            #include<algorithm> 头文件下,链表排序,默认是升序

multimap<int, string>

emplace():向容器中添加“新键值对”的效率,要比 insert() 方法高。

2. 难点:

相同出现频率,按字母顺序排序

3. 思路

1.计算频率,将元素放入unordered_map中
2.频率排序,将unordered_map的first,second倒置放入multimap中
3.遍历multimap元素,碰到频率相同的就放入一个临时数组中进行字母顺序排序,当频率不同时,就把数组中的元素放到需要返回的数组中
<==就是利用数据结构倒来倒去==>

变量定义的解释

vector<string> vec: 需要返回的数组

unordered_map<string, int> maps:
maps.first为words里的单个单词(string)-----> maps.second为单个string的频率(int)

multimap<int, string> res_topmap:
res_topmap.first为单个string的频率(int)-----> res_topmap.second 为words里的单个单词(string)

vector<string> sort_vec; 临时的用于按字母顺序排序相同频率的数组

4. 代码注释

class Solution {
public:
  vector<string> topKFrequent(vector<string>& words, int k) {
    vector<string> vec;                 /*需要返回的数组*/
    if (words.empty())                  /*words为空返回空数组*/
        return vec;
    unordered_map<string, int> maps;    /*用于统计每个单词的频率*/
    multimap<int, string> res_topmap;   /*按单词频率排序*/
    for (auto i : words)
        maps[i]++;                      /*将单词放入unordered_map*/
    for (auto item = maps.begin(); item != maps.end(); item++)
    { 
        res_topmap.emplace(item->second, item->first);  /*maps的first为res_topmap的second,maps的second为res_topmap的first,将键值对放入可重复map中。 */
    }

    /*注意此时res_ropmap的排序频率从小到大,而字母的顺序为从大到小(下面调整字母顺序)*/
    
    vector<string> sort_vec;                /*定义一个相同频率字母顺序排序*/
    int last = res_topmap.rbegin()->first;  /*记录上一个元素的频率*/
    for (auto item = res_topmap.rbegin(); item != res_topmap.rend(); item++) /*反向遍历,反向频率从大到小*/
    {  
        if (item != res_topmap.rbegin() && item->first != last) /*如果当前元素频率和前一个频率不相等,并且不是第一个元素(第一个元素没有前一个元素)*/    
        {
            sort(sort_vec.begin(), sort_vec.end()); /*字符串按字母顺序从小到大排序*/
            for (auto i : sort_vec)     /*遍历sort_vec,将里面元素按顺序压入需要返回的vec中*/
            {
                vec.push_back(i);
                if (vec.size() >= k)    /*题目只需要返回k个单词*/
                    return vec;
            }
            sort_vec.clear();           /*清空vector<string>*/
        }
        sort_vec.push_back(item->second);   /*相同频率的就压入sort_vec中*/  
        last = item->first;             /*移动到下一个元素之前保存到last中*/
    }
    if (!sort_vec.empty())              /*考虑到后面的元素频率相同,sort_vec中还有元素没有压入返回的vec中*/
    {
        sort(sort_vec.begin(), sort_vec.end()); /*同上*/
        for (auto i : sort_vec)
        {
            if (vec.size() >= k)
                return vec;
            vec.push_back(i);
        }
    }
    return vec;
}
};

不太喜欢压行

4. 总结反思

    vector<string> topKFrequent(vector<string>& words, int k) {
vector<string> vec;
map<string, int> maps;
multimap<std::pair<int, string>, string> res_topmap;
for (auto i : words)
    maps[i]++;
for (auto item = maps.begin(); item != maps.end(); item++)
{
    string str;
    for (auto k : item->first)
    {
        str.push_back('z'-k+'a');
    }
    res_topmap.emplace(std::pair<int,string>(item->second,str), item->first);
}
for (auto item = res_topmap.rbegin(); item != res_topmap.rend() && k > 0; item++)
{
    vec.push_back(item->second);
    k--;
}

return vec;
}
一开始用这样的类型结构处理省事,但测试到104这个点有点麻烦,默认的字母顺序是相反的并且难以改动,干脆代码重构了。  

alt 测试图片]