前K个高频单词

问题

给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

示例 1:

输入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。
    注意,按字母顺序 "i" 在 "love" 之前。

示例 2:

输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词,
    出现次数依次为 4, 3, 2 和 1 次。

解析

核心是采用map的计数功能。同时采用sort算法,进行排序。

代码

class Solution {
public:

    struct Com
    {
        bool operator()(pair<string, int> kv1, pair<string, int> kv2)   //返回bool
        {
           return kv1.second > kv2.second || (kv1.second == kv2.second && kv1.first < kv2.first); 
        }
    };

    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int> CountMap;
        for (auto& str : words)  //统计数据
        {
           CountMap[str]++;     //第一次,插入,计数++变成1
        }

        //CountMap内部已经是字典序排序
        
        //根据V去排序   //只要容器 B 支持从迭代器范围进行初始化,并且容器 A 和容器 B 存储的元素类型相同,你就可以使用容器 A 的迭代器来构造容器 B。
        vector<pair<string, int>> SortV(CountMap.begin(), CountMap.end());

        //sort不稳定,重写一个稳定的排序
        sort(SortV.begin(), SortV.end(), Com());    //需要的是一个对象作为参数,而不是别的

        vector<string> vec;

        for (size_t i = 0; i < k; ++i)
        {
            vec.push_back(SortV[i].first);
        }

        return vec;

    }
};

注意点:

1. 只要容器 B 支持从迭代器范围进行初始化,并且容器 A 和容器 B 存储的元素类型相同,你就可以使用容器 A 的迭代器来构造容器 B。

2.Com()是一个匿名对象,由于重载了operator(),所以这个匿名对象可以进行operator()接口的调用

匿名对象的operator接口的形参,采用的是*iterator之后的结果

sort函数支持传入仿函数对象进行重新规整排序方式

3.           return kv1.second > kv2.second || (kv1.second == kv2.second && kv1.first < kv2.first); 可以按照second的降序与字典序返回
 

4.

   for (auto& str : words)  //统计数据

        {

           CountMap[str]++;     //第一次,插入,计数++变成1

        }

第一次指向插入,然后++变成1              后续只进行++

5.为什么转化到vector之后才进行sort排序呢?这是因为sort的迭代器只支持随机迭代器

6.

map已经是字典序了,但是sort内部是快排,不是一个稳定的排序
稳定:相对顺序不变
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法,而堆排序、快速排序、希尔排序和选择排序是不稳定的排序算法。

解析

这段代码是一个 C++ 类 Solution 的定义,其中包含了一个方法 topKFrequent,该方法用于找出一个字符串数组中出现频率最高的前 k 个单词。以下是代码的详细解读:

类成员

  • Com 结构体:这是一个自定义的比较类(仿函数),用于定义 pair<string, int> 类型的比较逻辑。它重载了 operator(),使得可以比较两个键值对(key-value pairs)。比较逻辑如下:
    • 首先比较两个键值对的第二个元素(即值),如果第一个键值对的值大于第二个键值对的值,则返回 true
    • 如果两个键值对的值相等,则比较它们的第一个元素(即键),按照字典序比较字符串,如果第一个键值对的键小于第二个键值对的键,则返回 true

topKFrequent 方法

  • 输入参数:一个 vector<string> 类型的 words 和一个整数 k
  • 返回类型:一个 vector<string>,包含出现频率最高的前 k 个单词。

方法步骤:

  1. 统计频率

    • 使用 map<string, int> 类型的 CountMap 来统计每个单词出现的次数。
    • 遍历输入的 words 向量,对于每个单词 str,将其在 CountMap 中的计数增加 1。
  2. 创建排序向量

    • 使用 CountMap 的迭代器范围来初始化一个 vector<pair<string, int>> 类型的 SortV 向量。由于 map 内部是按键(即字符串)排序的,因此 SortV 初始化时已经按照键的字典序排好序。
  3. 排序

    • 使用 std::sort 函数对 SortV 进行排序。由于 std::sort 默认是不稳定的排序算法,但在这里我们通过提供一个自定义的比较类 Com(),可以确保排序时如果两个元素的频率相同,它们会保持原有的字典序顺序。
    • Com() 创建了一个 Com 类型的匿名对象,并作为比较函数传递给 std::sort
  4. 提取结果

    • 创建一个 vector<string> 类型的 vec 向量,用于存储结果。
    • 遍历排序后的 SortV 向量,将前 k 个元素的键(即单词)添加到 vec 中。
  5. 返回结果

    • 返回 vec,它包含了出现频率最高的前 k 个单词。

注意事项:

  • std::sort 在 C++ 标准库中实际上是稳定的,所以这里提到的“重写一个稳定的排序”是不必要的。std::sort 保证相同元素之间的相对顺序不会改变。
  • 代码中注释提到的“容器 A 和容器 B 存储的元素类型相同”是指 map 和 vector 中的元素类型都是 pair<string, int>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值