[Algorithm][堆][优先级队列][最后一块石头的重量][数据流中的第K大元素][前K个高频单词][数据流中的中位数]详细讲解

本文主要是介绍[Algorithm][堆][优先级队列][最后一块石头的重量][数据流中的第K大元素][前K个高频单词][数据流中的中位数]详细讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1.最后一块石头的重量
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 2.数据流中的第 K 大元素
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 3.前K个高频单词
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 4.数据流的中位数
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现


1.最后一块石头的重量

1.题目链接

  • 最后一块石头的重量

2.算法原理详解

  • 思路:利用大根堆
    • 将所有的⽯头放⼊⼤根堆中
    • 每次拿出前两个堆顶元素粉碎⼀下,如果还有剩余,就将剩余的⽯头继续放⼊堆中

3.代码实现

int LastStoneWeight(vector<int>& stones) 
{priority_queue<int> heap; // STL默认大根堆for(auto& x : stones){heap.push(x);}// 模拟过程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;
}

2.数据流中的第 K 大元素

1.题目链接

  • 数据流中的第 K 大元素

2.算法原理详解

  • 本题为TOP-K的运用
  • TOP-K问题,一般用一下两种方法来解决
    • O ( N ∗ l o g K ) O(N*logK) O(NlogK)
    • 快速选择算法 O ( N ) O(N) O(N)
  • 用堆解决TOP-K问题
    • 用数据集合中前K个元素来建堆
      • 前k个最大的元素:建小堆
      • 前k个最小的元素:建大堆
    • 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
    • 走完以后,堆里面的k个数,就是最大的前k个
  • 流程
    • 创建一个大小为k的堆(大根堆/小根堆)
    • 循环
      • 依次进堆
      • 判断堆的大小是否超过k
  • 如何判断是否用大根堆还是小根堆,为什么呢?
    • TOP-K-MAX:建小堆
      • 依次进堆,当heap.size() > k时,弹出堆顶元素
      • 因为堆顶元素是最小的,绝对不会是TOP-K-MAX
    • TOP-K-MIN:建大堆
      • 依次进堆,当heap.size() > k时,弹出堆顶元素
      • 因为堆顶元素是最大的,绝对不会是TOP-K-MIN

3.代码实现

class KthLargest 
{// 创建一个大小为k的小根堆priority_queue<int, vector<int>, greater<int>> heap;int _k = 0;
public:KthLargest(int k, vector<int>& nums) {_k = k;for(auto& x : nums){heap.push(x);if(heap.size() > _k){heap.pop();}}}int add(int val) {heap.push(val);if(heap.size() > _k){heap.pop();}return heap.top();}
};

3.前K个高频单词

1.题目链接

  • 前K个高频单词

2.算法原理详解

  • 思路:利用"堆"来解决TOP-K问题
    • 预处理原始的字符串数组
      • 哈希表统计每一个单词出现的频次
    • 创建一个大小为k的堆
      • 频次:小根堆
      • 字典序(频次相同的时候):大根堆
    • 循环
      • 让元素一次进堆
      • 判断
    • 提取结果
      • 把数组逆序

3.代码实现

 class Solution 
{typedef pair<string, int> PSI;struct Cmp{bool operator()(PSI& a, PSI& b){// 频次相同,字典序按大根堆排序if(a.second == b.second){return a.first < b.first;}// 频次按小根堆排序return a.second > b.second;}};
public:vector<string> TopKFrequent(vector<string>& words, int k) {// 统计每个单词出现的次数unordered_map<string, int> hash;for(auto& str : words){hash[str]++;}// 创建一个大小为k的堆priority_queue<PSI, vector<PSI>, Cmp> heap;// TOP-Kfor(auto& psi : hash){heap.push(psi);if(heap.size() > k){heap.pop();}}// 提取结果,逆序heapvector<string> ret(k);for(int i = k - 1; i >= 0; i--){ret[i] = heap.top().first;heap.pop();}return ret;}
};

4.数据流的中位数

1.题目链接

  • 数据流的中位数

2.算法原理详解

  • 思路一:直接sort

    • 时间复杂度:
      • add() O ( N ∗ l o g N ) O(N*logN) O(NlogN)
      • find() O ( 1 ) O(1) O(1)
    • 每次add(),都sort一遍,时间复杂度很恐怖
      请添加图片描述
  • 思路二:插入排序的思想

    • 时间复杂度:
      • add() O ( N ) O(N) O(N)
      • find() O ( 1 ) O(1) O(1)
    • 每次add(),都在原数据基础上进行插入排序,时间复杂度有所改善
      请添加图片描述
  • 思路三:利用大小堆来维护数据流中位数

    • 此问题时关于**「堆」的⼀个「经典应⽤」**
    • 时间复杂度:
      • add() O ( l o g N ) O(logN) O(logN)
      • find() O ( 1 ) O(1) O(1)
    • 将整个数组「按照⼤⼩」平分成两部分(如果不能平分,那就让较⼩部分的元素多⼀个)
      • m == n
      • m > n -> m == n + 1
    • 将左侧部分放⼊「⼤根堆」中,然后将右侧元素放⼊「⼩根堆」中
    • 这样就能在 O ( 1 ) O(1) O(1)的时间内拿到中间的⼀个数或者两个数,进⽽求的平均数
      请添加图片描述
  • 细节add()时,如何维护m == n || m > n -> m == n + 1

    • m == n
      请添加图片描述

    • m > n -> m == n + 1
      请添加图片描述


3.代码实现

class MedianFinder 
{priority_queue<int> left; // 大根堆priority_queue<int, vector<int>, greater<int>> right; // 小根堆
public:MedianFinder() {}void AddNum(int num) {if(left.size() == right.size()){if(left.empty() || num <= left.top()){left.push(num);}else{right.push(num);left.push(right.top());right.pop();}}else{if(num <= left.top()){left.push(num);right.push(left.top());left.pop();}else{right.push(num);}}}double FindMedian() {if(left.size() == right.size()){return (left.top() + right.top()) / 2.0;}else{return left.top();}}
};

这篇关于[Algorithm][堆][优先级队列][最后一块石头的重量][数据流中的第K大元素][前K个高频单词][数据流中的中位数]详细讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/961790

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

沁恒CH32在MounRiver Studio上环境配置以及使用详细教程

目录 1.  RISC-V简介 2.  CPU架构现状 3.  MounRiver Studio软件下载 4.  MounRiver Studio软件安装 5.  MounRiver Studio软件介绍 6.  创建工程 7.  编译代码 1.  RISC-V简介         RISC就是精简指令集计算机(Reduced Instruction SetCom

arduino ide安装详细步骤

​ 大家好,我是程序员小羊! 前言: Arduino IDE 是一个专为编程 Arduino 微控制器设计的集成开发环境,使用起来非常方便。下面将介绍如何在不同平台上安装 Arduino IDE 的详细步骤,包括 Windows、Mac 和 Linux 系统。 一、在 Windows 上安装 Arduino IDE 1. 下载 Arduino IDE 打开 Arduino 官网

遮罩,在指定元素上进行遮罩

废话不多说,直接上代码: ps:依赖 jquer.js 1.首先,定义一个 Overlay.js  代码如下: /*遮罩 Overlay js 对象*/function Overlay(options){//{targetId:'',viewHtml:'',viewWidth:'',viewHeight:''}try{this.state=false;//遮罩状态 true 激活,f

GPT系列之:GPT-1,GPT-2,GPT-3详细解读

一、GPT1 论文:Improving Language Understanding by Generative Pre-Training 链接:https://cdn.openai.com/research-covers/languageunsupervised/language_understanding_paper.pdf 启发点:生成loss和微调loss同时作用,让下游任务来适应预训