前K个高频元素——栈与队列

先放代码:


class Solution {
public:
    class mycomperation {
        public://注意这里的问题
        bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
            return lhs.second > rhs.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        // 先进行排序
        unordered_map<int, int> umap;
        for (int i = 0; i < nums.size(); i++) {
            umap[nums[i]]++;
        }
        // 定义好了之后,开始维护小顶堆
        priority_queue<pair<int, int>, vector<pair<int, int>>, mycomperation> myque;
        // 开始排序
        for (unordered_map<int, int>::iterator it = umap.begin(); it != umap.end(); it++) {
            myque.push(*it); // 所以其实可以把迭代器理解为一个指针类型
            // 我们只需要维护k个元素即可
            if (myque.size() > k) {
                myque.pop();
            }
        }
        // 维护好了之后就是结果的输出,注意是倒序输出
        vector<int> result;
        for (int i = k - 1; i >= 0; i--) {
            result.push_back(myque.top().first);
            myque.pop();
        }
        return result;
    }
};

里面用到的东西很多,涉及到了运算符重载,比较器,堆,优先级队列,哈希表等内容。一个一个来。

1、运算符重载

在 C++ 中,operator() 被称为 函数调用运算符。它允许我们像调用函数一样调用类的对象。也就是说,如果一个类重载了 operator(),那么你可以像调用函数一样,通过 () 来调用这个类的实例。

而一般我们常用运算符重载的方式来构建堆的比较器,这样堆就可以使用类内的这个重载过的运算符。

2、堆的比较器

堆的比较器:我们使用 operator() 来定义堆中元素的比较规则。比较器是一个“函数对象”,可以让你自定义堆的排序方式。

3、堆

堆可以理解为一个完全二叉树,就是节点都是满的,而且最下面的节点尽可能靠左。然后堆又分为大顶堆和小顶堆,一个是从大到小一个是从小到大。然后通常通过 优先队列(std::priority_queue 来实现。std::priority_queue 默认是最大堆(即堆顶是最大的元素),但可以通过自定义比较器来实现最小堆或其他排序规则。

4,优先级队列

C++ STL 提供了一个容器适配器 std::priority_queue,可以用来实现优先级队列。默认情况下,std::priority_queue 是一个最大优先级队列(即堆顶元素为最大值)。它使用 二叉堆 来实现,因此插入和删除操作的时间复杂度为 O(log n)

// 使用自定义的比较器创建一个最小优先级队列 std::priority_queue<int, std::vector<int>, MinComparator> pq;

5.哈希表

这个是前面内容,简单回顾一下unordered_map是无序的,然后我们一般遍历里面的内容时采用迭代器的方式,注意

for (unordered_map<int, int>::iterator it = umap.begin(); it != umap.end(); it++)
差不多就这些、
posted @ 2024-11-20 15:52  小橘0815  阅读(1)  评论(0编辑  收藏  举报