347.前k个高频元素

记录新手小白的做题历程。


题目:

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]


思路:这个我最先想到的是哈希表,key用来存整数,而value用来存值,然后用sort来从大到小排序,最后取出前k个就可以数字。

但是sort对哈希表的排序规则我不会写啊qwq。


我在评论区里看到一个 大佬,和我的思路很像,他用哈希表存好数据后,将数据又放入vector,再对value进行排序

点击链接 

我不知道改这么自定义sort的排序,之前没有接触过pair,也不知道该怎么传参。

到网上搜了之后,发现大家都没有直接对哈希表unordered_map排序,而是和这个大佬一样,借用vector<pair<int,int>>

class Solution {
public:
    // 升序排序
    static int cmp(pair<int, int> a, pair<int, int> b){
        return a.second > b.second;
    }
    vector<int> topKFrequent(vector<int>& nums, int k) {
        /*
            利用unordered_map + 自定义排序
        */
        vector<int> res;
        unordered_map<int, int> ht;
        for(int n:nums){
            ht[n]++;
        }
        // 转为pair以对value进行排序
        vector<pair<int, int>> tmp;
        for(auto it = ht.begin(); it!=ht.end(); it++){
            tmp.push_back(pair<int, int>(it->first, it->second));
        }
        sort(tmp.begin(), tmp.end(), cmp);
        // 获取答案
        for(int i = 0; i < k; i++){
            res.push_back(tmp[i].first);
        }
        return res;

    }
};

收获:

1.

自定义sort的排序规则 

不过为什么他的参数里没有加&呢?加了之后也代码也可以实现

2.将哈希表中数据放入vector,tmp.push_back(pair<int,int>(tmp->first,tmp->second));

我是这样写的

3.它这个排序是升序?理解一下


官方代码:

官方的思路与我的差不多(不过应该大家差不多都这么想的吧qwq)

用了最小堆来排序。

class Solution {
public:
    static bool cmp(pair<int, int>& m, pair<int, int>& n) {//排序的规则
        return m.second > n.second;
    }

    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> occurrences;
        for (auto& v : nums) {//将所有元素放入哈希表,无序
            occurrences[v]++;
        }

        // pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数,小项堆
        priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);
        for (auto& [num, count] : occurrences) {//遍历哈希表中的元素,num是数,后面是出现的次数
            if (q.size() == k) {//如果已经装了K个元素
                if (q.top().second < count) {//最顶端的数字小于它,将最小项弹出,放入这一个
                    q.pop();
                    q.emplace(num, count);
                }
            } else //未满k个,可以继续装
                q.emplace(num, count);
            }
        }
        vector<int> ret;
        while (!q.empty()) {//放入答案
            ret.emplace_back(q.top().first);
            q.pop();
        }
        return ret;
    }
};

思路:1.统计元素出现次数并放入哈希表 

2,创建最小堆(只有最小堆才能剔除小值保留大值)

3,遍历哈希表,依次放入元素,若最小堆中的size未超过K,可以直接放入数据,若多于k,则需要将堆顶与新值进行比较,若新值大,则需要弹出堆顶,插入新值。

4,最后创建答案数组,将最大堆的元素放入数组内。

收获:

1.  priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);
        //设了一个最大堆用来排序,改变三个参数,第一个是存储的数据类型,第二个是容器类型,第三个是比较方式,重新创建的规则

2. 没有见过decltype,了解一下。emmm,为什么最后面是q(cmp)啊,搞不懂搞不懂。理解不了就死记。 创建堆时的cmp不能去掉,否则会报错。

decltype

3.是pair,不是pairs

4.comp前面一定要有static,其函数需要对元素排序,所以参数需要加&,comp内的参数如何写要记住

5.auto无法遍历堆,像这样写for(auto& [num,count]:q)是错误的,但vector可以,

for(auto& [num,count]:occurrences)没错,所以代码最后是用堆是否为空来决定是否进行循环,而不是遍历q

方法二:快速排序

class Solution {
public:
    void qsort(vector<pair<int, int>>& v, int start, int end, vector<int>& ret, int k) {
        int picked = rand() % (end - start + 1) + start;
        swap(v[picked], v[start]);

        int pivot = v[start].second;
        int index = start;
        for (int i = start + 1; i <= end; i++) {
            if (v[i].second >= pivot) {
                swap(v[index + 1], v[i]);
                index++;
            }
        }
        swap(v[start], v[index]);

        if (k <= index - start) {
            qsort(v, start, index - 1, ret, k);
        } else {
            for (int i = start; i <= index; i++) {
                ret.push_back(v[i].first);
            }
            if (k > index - start + 1) {
                qsort(v, index + 1, end, ret, k - (index - start + 1));
            }
        }
    }

    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> occurrences;
        for (auto& v: nums) {
            occurrences[v]++;
        }

        vector<pair<int, int>> values;
        for (auto& kv: occurrences) {
            values.push_back(kv);
        }
        vector<int> ret;
        qsort(values, 0, values.size() - 1, ret, k);
        return ret;
    }
};

我的天哪,这道题肝了我几个小时,还有快速排序方法实在是懒得看了······

记在这里,下次一定。 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值