最小堆

Leetcode 480.滑动窗口中位数

。_饼干妹妹 提交于 2020-03-27 18:28:03
滑动窗口中位数 中位数是有序序列最中间的那个数。如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。 例如: [2,3,4],中位数是 3 [2,3],中位数是 (2 + 3) / 2 = 2.5 给出一个数组 nums,有一个大小为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。 例如: 给出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。 窗口位置 中位数 --------------- ----- [1 3 -1] -3 5 3 6 7 1 1 [3 -1 -3] 5 3 6 7 -1 1 3 [-1 -3 5] 3 6 7 -1 1 3 -1 [-3 5 3] 6 7 3 1 3 -1 -3 [5 3 6] 7 5 1 3 -1 -3 5 [3 6 7] 6 因此,返回该滑动窗口的中位数数组 [1,-1,-1,3,5,6]。 提示: 假设k是合法的,即:k 始终小于输入的非空数组的元素个数. 解题思想 题目会给一个数组,和一个滑动窗口的大小K,让你找出当这个窗口滑动的过程中,这个K的窗口内的中位数分别是多少? 最naive的方式就是在k个窗口内排序就好,这里不解释(因为开销很大啊,(n-k+1) * (k*log(k)

延迟任务的实现总结

早过忘川 提交于 2020-03-23 08:48:25
上一篇 写了使用RabbitMQ来实现延迟任务的实现,其实实现延迟任务的方式有很多,各有利弊,有单机和分布式的。在这里做一个总结,在遇到这类问题的时候希望给大家一个参考和思路。 延迟任务有别于定式任务,定式任务往往是固定周期的,有明确的触发时间。而延迟任务一般没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发另一个事件。延迟任务相关的业务场景如下: 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时。 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单。 下面我们来探讨一些方案,其实这些方案没有好坏之分,和系统架构一样,只有最适合。对于数据量较小的情况下,任意一种方案都可行,考虑的是简单明了和开发速度,尽量避免把系统搞复杂了。而对于数据量较大的情况下,就需要有一些选择,并不是所有的方案都适合了。 1. 数据库轮询 这是比较常见的一种方式,所有的订单或者所有的命令一般都会存储在数据库中。我们会起一个线程去扫数据库或者一个数据库定时Job,找到那些超时的数据,直接更新状态,或者拿出来执行一些操作。这种方式很简单,不会引入其他的技术,开发周期短。 如果数据量比较大,千万级甚至更多,插入频率很高的话,上面的方式在性能上会出现一些问题,查找和更新对会占用很多时间,轮询频率高的话甚至会影响数据入库

斐波那契堆(二)之 C++的实现

99封情书 提交于 2020-03-18 05:32:33
概要 上一章 介绍了斐波那契堆的基本概念,并通过C语言实现了斐波那契堆。本章是斐波那契堆的C++实现。 目录 1. 斐波那契堆的介绍 2. 斐波那契堆的基本操作 3. 斐波那契堆的C++实现(完整源码) 4. 斐波那契堆的C++测试程序 转载请注明出处: http://www.cnblogs.com/skywang12345/p/3659069.html 更多内容: 数据结构与算法系列 目录 (01) 斐波那契堆(一)之 图文解析 和 C语言的实现 (02) 斐波那契堆(二)之 C++的实现 (03) 斐波那契堆(三)之 Java的实现 斐波那契堆的介绍 斐波那契堆(Fibonacci heap)是一种可合并堆 ,可用于实现合并优先队列 。它比二项堆具有更好的平摊分析性能,它的合并操作的时间复杂度是O(1)。 与二项堆一样,它也是由一组堆最小有序树组成,并且是一种可合并堆。 与二项堆不同的是,斐波那契堆中的树不一定是二项树;而且二项堆中的树是有序排列的,但是斐波那契堆中的树都是有根而无序的。 斐波那契堆的基本操作 1. 基本定义 template <class T> class FibNode { public: T key; // 关键字(键值) int degree; // 度数 FibNode<T> *left; // 左兄弟 FibNode<T> *right; //

大数据处理面试题

假装没事ソ 提交于 2020-02-29 01:57:58
1. 给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url? 方an1:可以估计每个文件安的大小为50G×64=320G,远远大于内存限制的4G。所以不可能将其完全加载到内存中处理。kao虑采取分而治之的方法。 s 遍历文件a,对每个url求取 ,然后根据所取得的值将url分别存储到1000个小文件(记为 )中。这样每个小文件的大约为300M。 s 遍历文件b,采取和a相同的方式将url分别存储到1000各小文件(记为 )。这样处理后,所有可能相同的url都在对应的小文件( )中,不对应的小文件不可能有相同的url。然后我们只要求出1000对小文件中相同的url即可。 s 求每对小文件中相同的url时,可以把其中一个小文件的url存储到hash_set中。然后遍历另一个小文件的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。 方an2:如果允许有一定的错误率,可以使用Bloom filter,4G内存大概可以表示340亿bit。将其中一个文件中的url使用Bloom filter映射为这340亿bit,然后挨个读取另外一个文件的url,检查是否与Bloom filter,如果是,那么该url应该是共同的url(注意会有一定的错误率)。 2. 有10个文件,每个文件1G

215. 数组中的第K个最大元素

自闭症网瘾萝莉.ら 提交于 2020-02-15 04:48:19
215. 数组中的第K个最大元素 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 示例 1: 示例 2: 说明: 你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。 2.方法一(快速排序) 利用快速排序的思想,对数组进行递减排序,把第k大的元素放到正确的位置。 算法过程: 1.利用partition()随机获取一个元素的下标index。 2.如果index > k-1,说明第k大元素在index的左边,right = index - 1。 2.如果index < k-1,说明第k大元素在index的右边,left = index + 1。 3.当index == k-1,退出循环,返回nums[index]。 3.代码 class Solution { public : int findKthLargest ( vector < int > & nums , int k ) { int left = 0 ; int right = nums . size ( ) - 1 ; int index = partition ( nums , left , right ) ; while ( index != k - 1 ) { if ( index > k - 1 ) { right = index

旧街凉风 提交于 2020-02-09 11:49:08
一、什么是堆 1. 定义 设有n个数据元素组成的序列{a1, a2, ..., an},这些数据元素是一棵完全二叉树中的节点,如果对于所有节点,父节点数据总是大于子节点数据,则称该序列为大根堆(最大堆),反之,若父节点数据总是小于子节点数据,则称为小根堆(最小堆)。 2. 应用 一般用于比较快速的取得一个数列的最大或最小值。 二、 堆的实现 由于堆的数据是一棵完全二叉树的节点,所以可以很方便的使用数组进行存储,直接利用下标来表示父节点与子节点之间的关系,下标为i的元素的左子节点的下标为2*i+1,右子节点的下标为2*2+2。 下面是Go语言实现的最小堆的代码,最大堆的实现可以此类推。实现代码的核心部分为向下调整shiftDown()和向上调整shiftUp()两个方法,前者为堆初始化或删除时调用,后者为堆插入时调用。 /** * 最小堆 * author:JetWu * date:2020.02.08 */ package minHeap import ( "errors" "fmt" ) /** * 最小堆结构 **/ type MinHeap struct { slice []int size int //最小堆大小 } /** * 创建一个空最小堆 **/ func NewMinHeap() *MinHeap { return &MinHeap{ slice: make([

面试题41:数据流中的中位数

有些话、适合烂在心里 提交于 2020-02-07 22:16:56
1、题目描述:    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。 2、思路: 看到这道题很自然的想到常规解法,对数组进行排序,也就是说只要插入一个数据,就对数组进行一次排序,就要移动后边的数字,因此插入数据的时间复杂度为o(n),而从排序数组中取出中位数的时间复杂度为O(1)。这种方法比较显然,还不是最终解法。   而另一种解法就是用自平衡的二叉搜索树(AVL)树,通常AVL树的平衡因子是左右子树的高度差。可以稍作修改,把AVL的平衡因子改为左右子树的节点数目之差。这样插入新的节点的时间复杂度为O(logn),而取出中位数的时间复杂度为O(1)。而AVL树是没有库函数的,因此不好实现。   最终的解法:可以先观察如下数组 N1 N2 ...... Nm Nm+1 .......N2m N2m+1 N1 N2 ...... Nm Nm+1 .......N2m   上边的数组元素个数为奇数个,中位数是Nm+1   下边的为偶数个元素,中位数是Nm+Nm+1除以2   无论是奇数个元素还是偶数个,整个数组被分成了两部分

POJ 1442 优先队列

谁都会走 提交于 2020-02-07 02:09:14
题意:有一些ADD和GET操作。n次ADD操作,每次往序列中加入一个数,由ADD操作可知序列长度为1-n时序列的组成。GET操作输入一个序列长度,输出当前长度序列第i大的元素的值。i初始为0,每次GET操作i先加1。给出的GET操作输入非降。 思路:求长度为k的序列的第i大元素。优先队列维护最大堆和最小堆分别存放前i-1大的元素和第i-第k大的元素。将当前序列的元素压入最小堆,如果最小堆的最小数大于最大堆的最大数则进行交换,保证最大堆中的所有数小于最小堆。因为i值每进行一次自增1,所以每次GET操作后将最小堆中的最小数弹出存入最大堆。 #include<cstdio> #include<queue> using namespace std; priority_queue<int> bigque; priority_queue<int, vector<int> ,greater<int> > smallque; int num[30010]; int main() { int n,m,x; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&num[i]); int k=1; for(int i=1;i<=m;i++) { scanf("%d",&x); while(k<=x) { smallque.push(num[k]);

最小堆定时器 —— 实现

时光怂恿深爱的人放手 提交于 2020-02-04 07:02:13
最小堆定时器 我们将使用内核现有的数据结构和同步结构的 API 来说明怎样设计一个最小堆定时器,并扩展语义。内核在 2.6.16 就已经使用最小堆实现了一个叫着 hrtimer 的定时器,但是语义较复杂,我们将使用它的一些现成的数据结构和辅助函数来实现 timer_list 定时器。 最小堆定时器队列 最小堆数据结构的语义是有序的、线性的数据结构,“最小”的成员在容器的前端。在 内核定时器 一文中,我们讲解了时间轮算法,是由多个有规律的松散定时器队列构成的,这里我们用最小堆来管理排队的定时器,所以最小堆具有队列语义。我们用使用内核提供的红黑树来实现。 关于红黑树的实现网上有很多文章,我们这专注实现一个最小堆。 数据结构 struct timerqueue_node { struct rb_node node ; uint64_t expires ; /*我们将使用绝对时间,来判断是否超时*/ } ; struct timerqueue_head { struct rb_root head ; struct timerqueue_node * next ; } ; 还是内核一贯的风格, struct timerqueue_node 还是作为一个成员在需要排序的对象中,然后使用 container_of() 计算被浸入的对象的指针。 struct timerqueue_head

剑指offer 最小的K个数

半世苍凉 提交于 2020-02-01 14:37:12
1.题目 输入 n 个整数,找出其中最小的 K 个数。例如输入 4,5,1,6,2,7,3,8 这 8 个数字,则最小的 4 个数字是 1,2,3,4 。 来源:剑指offer 链接: https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 2.我的题解 2.1最小堆 使用最小堆实现: 实现一个最小堆,借助 vector ,下标从 1 开始存储; 实现删除最小元素的函数 del ,要求删除后保持堆有序,返回删除的元素; 利用输入数据建堆; 连续执行 K 次 del ,并将函数返回值添加到输出结果。 时间复杂度: O(n+klogn) 空间复杂度: O(n) 下沉操作构建堆: 确定堆的大小,开辟空间并填入数值; 从第一个非叶节点开始做下沉操作,直到第一个节点。 构建堆的复杂度计算: 以 n 个节点,树高 h 的满二叉树(堆)为例,显然 h=log(n+1) ; 各层节点关系: 设想一个满二叉树,下一层的节点数总是翻倍,而总结点个数约等于最后一层节点个数的两倍(实际上就少1);故每一层的节点数和都可以由 n 表示。 堆的层数