当前位置: 首页 > news >正文

优先级队列的应用

第一题:

题解思路:

1、建立降序的优先级队列(底层是通过大堆来实现);

2、取最大的两个数来相减得到的结果再加入到优先级队列中(优先级队列会自动的排序);

3、返回队列的头部或者0即可;

 题解代码:

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) {
        // 创建大堆
        priority_queue<int> heap;
        //
        for (auto& e : stones)
            heap.push(e);
        // 碰撞操作
        while (heap.size() > 1) {
            // 取队顶元素
            int a = heap.top();
            heap.pop();
            // 取第二大的
            int b = heap.top();
            heap.pop();
            if (a > b) {
                heap.push(a - b);
            }
        }
        return heap.size()?heap.top():0;
    }
};

第二题:

题解思路: 

题解代码:

class KthLargest {
    priority_queue<int, vector<int>, greater<int>> heap;
    int _k;

public:
    KthLargest(int k, vector<int>& nums) {
        _k = k;
        for (auto& e : nums) {
            heap.push(e);
            if (heap.size() > _k) {
                heap.pop();
            }
        }
    }

    int add(int val) {
        heap.push(val);
        if (heap.size() > _k)
            heap.pop();
        return heap.top();
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */

小结:

回答为什么要第k大,建小堆,第K小,建大堆的问题?

        其实可以从上面的代码能够看出,return(返回) 的是heap.top()元素;就是说,第K大或者第k小,都是从后面往前数的,也即,升序的序列(小堆),从后往前数才能数到第K大的元素,而降序的序列(大堆),从后往前数才能数到第K小的元素;-------这就是为什么建大堆找K小,建小堆找第K大的原因。

 第三题:

解题思路:

1、建立hash表统计次数;

2、建立优先级队列,并根据要求(次数按小堆,string按大堆)重写仿函数;

3、提取队列中的top( )按照升序排列;

注意的细节:

1、队列中我们存pair<string,int>这个组合;

2、cmp中,次数int要求是前k大,就说明是升序排列,建小堆;

3、 对应的,当次数相同的时候,按照的是string中的字母顺序的前后(注意,字母是按ASCII码的大小来排列,值越大越靠前,值小的在后面)说明是降序排列,建大堆;

解题代码:

class Solution {
    typedef pair<string, int> PSI;
    // 实现自定的仿函数
    struct cmp {
        bool operator()(const PSI& a, const PSI& b) {
            if (a.second ==
                b.second) { // 次数相同,按字母的asc码的降序,建大堆(小的往下沉)
                return a.first < b.first;
            }
            // 次数不同就按次数的升序,前k个最大的,就是升序,建小堆(将大的往下沉)
            return a.second > b.second;
        }
    };

public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        // hash表统计次数
        unordered_map<string, int> hash;
        for (auto& e : words) {
            hash[e]++;
        }
        // 创建一个大小为k的优先级队列
        priority_queue<PSI, vector<PSI>, cmp> heap;
        // 主逻辑
        // 将hash表中所有的pair值存入到队列中
        for (auto& psi : hash) {
            heap.push(psi);
            if (heap.size() > k)
                heap.pop();
        }
        // 到这heap.top()是k个中次数最小的;而要求返回的数组中的从前往后是一次增大的;
        vector<string> ret(k);
        for (int i = k - 1; i >= 0; i--) {
            ret[i] = heap.top().first;
            heap.pop();
        }
        return ret;
    }
};

小结:

1、优先级队列就是大堆小堆的包装,常用来处理topK问题;

2、求K大就建小堆,队列是升序排列,优先级队列的top()是K个当中最小的;

3、求K小就建大堆,队列是将序排列,优先级队列的top()是K个当中最大的;

4、只有栈和优先级队列才用的是top(),而普通的队列queue只有front():

        ·取栈顶元素用top();

        ·取优先级队列中的队头元素用top();

        ·取队列中的队头元素用front();

 

 

相关文章:

  • LeetCode 3375.使数组的值全部为 K 的最少操作次数:O(1)空间——排序+一次遍历
  • 递增子序列
  • 【前缀和】 K 整除的⼦数组(medium)
  • 【系统分析师-第二遍(19-22)】
  • 题目练习之动态规划(一)
  • 面向对象的要素
  • 基于多模态大模型的ATM全周期诊疗技术方案
  • LeetCode 第41~43题
  • ffmpeg函数简介(封装格式相关)
  • ecovadis评级的重要性,如何进行ecovadis评级,当下贸易环境有啥影响
  • HttpServletRequest是什么
  • 光度立体三维重建——光源标定
  • NO.74十六届蓝桥杯备战|搜索算法-BFS|马的遍历|迷宫|Catch That Cow|八数码难题(C++)
  • 前端配置husky,commit-lint导致的git提交错误:git xx@0.0.0 lint:lint-staged
  • 告别数据孤岛:Telegraf-IoTDB 实现一站式监控数据闭环
  • 392. 判断子序列
  • 013_File和IO流
  • 蓝桥云客--黑白皇后
  • fisco-bcos 关于服务bash status.sh启动runing 中但是5002端口监听不到,出错的问题
  • Dynamic Programming(LeetCode 740)
  • 做网站 教程/免费发布推广平台
  • 广州网站服务/安卓手机优化软件哪个好
  • 青岛网站开发公司/搜狗官网
  • 做奥网站/长沙靠谱关键词优化服务
  • 玉树营销网站建设服务/小程序开发流程详细
  • 正常网站 月均ip pv/宁波网站推广