编程集训第3天:队列及堆排序思想--LeetCode滑动窗口的最大值(239)
编程集训第3天:队列及堆排序思想--LeetCode滑动窗口的最大值(239)
基础知识
一、队列(queue)
队列和栈一样,在实际程序的算法设计和计算机一些其他分支里,都有很多重要的应用,比如计算机操作系统对进程 or 作业的优先级调度算法,对离散事件的模拟算法,还有计算机主机和外部设备运行速度不匹配的问题解决等,很多很多。其实队列的本质还是线性表!只不过是一种特殊的或者说是受限的线性表,是这样的:
1)、限定在表的一端插入、另一端删除。 插入的那头就是队尾,删除的那头就是队头。也就是说只能在线性表的表头删除元素,在表尾插入元素。形象的说就是水龙头和水管,流水的水嘴是队头,进水的泵是队尾,管子中间不漏水不进水。这样呲呲的流动起来,想想就是这么个过程。
2)、先进先出 (FIFO结构)。显然我们不能在表(队列)的中间操作元素,只能是在尾部进,在头部出去,还可以类似火车进隧道的过程。(first in first out = FIFO 结构)
优先队列:
听这个名字就能知道,优先队列也是一种队列,只不过不同的是,优先队列的出队顺序是按照优先级来的;在有些情况下,可能需要找到元素集合中的最小或者最大元素,可以利用优先队列ADT来完成操作,优先队列ADT是一种数据结构,它支持插入和删除最小值操作(返回并删除最小元素)或删除最大值操作(返回并删除最大元素)
二、堆(heap)
堆是一颗具有特定性质的二叉树,堆的基本要求就是堆中所有结点的值必须大于或等于(或小于或等于)其孩子结点的值,这也称为堆的性质;堆还有另一个性质,就是当 h > 0 时,所有叶子结点都处于第 h 或 h - 1 层(其中 h 为树的高度,完全二叉树),也就是说,堆应该是一颗完全二叉树;
在下面的例子中,左边的树为堆(每个元素都大于其孩子结点的值),而右边的树不是堆:
基础知识参照
编程题目
题目描述:
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。
返回滑动窗口最大值。
C++代码实现:
- 方法一:优先队列
class Solution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k) { vector<int> result; priority_queue<pair<int,int>> Q; if (nums.size() < k || k < 1) return result; for (int i = 0; i < k-1; i++) Q.push(pair<int,int>(nums[i],i)); for (int i = k-1; i < nums.size(); i++) { Q.push(pair<int,int>(nums[i],i)); pair<int,int> p = Q.top(); while(p.second < i-(k-1)) { Q.pop(); p = Q.top(); } result.push_back(p.first); } return result; } };
优先队列:
优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认按元素值由大到小排序,可以重载“<”操作符来重新定义比较规则。
基本操作:
empty() 如果队列为空,则返回真
pop() 删除对顶元素,删除第一个元素
push() 加入一个元素
size() 返回优先队列中拥有的元素个数
top() 返回优先队列对顶元素,返回优先队列中有最高优先级的元素
- 方法二:双端数列
class Solution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k) { deque<int> q; int n=nums.size(); vector<int> res; if(n==0||k<1||n<k) return res; for(int i=0;i<n;i++) { while(!q.empty()&&nums[q.back()]<=nums[i]) q.pop_back(); q.push_back(i); if(q.front()==i-k) q.pop_front(); if(i>=k-1) res.push_back(nums[q.front()]); } return res; } };
思路:
维护一个双端队列,这个队列保存依次遍历的下标值。入队列的规则是比队尾小的数可以入队,比队尾大的数,将队列末尾所有小的数都清除直到遇到比这个数大的数位置。每到一个窗口,都从队头读取元素,如果元素已经超出窗口范围,就在看下一个元素。
知识回顾
【任务一】
数组:学习哈希表思想,并完成leetcode上的两数之和(1)及Happy Number(202)!(要求全部用哈希 思想实现!)(笔记整理中)
【任务二】
链表:学习单链表知识,实践环形链表(142,要求至少两种方法!)及反转一个单链表(206)(笔记整理中)
- leetcode之数组类之区间类-----OJ 56/57/435/239 重叠区间个数 合并区间 插入区间 滑动窗口最大值
- leetcode 239. Sliding Window Maximum 滑动窗口最大值Maximum + 优先级队列 + multiset + Heap
- Leetcode 239 Silding Window Maximum(滑动窗口的最大值)
- [LeetCode 239] Sliding Window Maximum (Queap/队列快速求最大值)
- leetcode 239. Sliding Window Maximum 双端队列 滑动窗口最大值
- 编程之美3.7队列中取最大值操作问题(新解法,空间复杂度比原解法低)
- lintcode 滑动窗口的最大值(双端队列)
- 编程集训第6天:递归实战--Leetcode的Letter Combinations of a Phone Number(17)及permutations(46)
- [LeetCode] 239. Sliding Window Maximum 滑动窗口最大值
- 《剑指offer》刷题笔记(栈和队列):滑动窗口的最大值
- 单调队列 —— 滑动窗口(滚动最大值)
- 编程之美-队列中取最大值操作问题
- 编程之美--3.7 队列中取最大值操作问题
- 第6章 堆排序 java实现 简单版 泛型版 最大优先级队列
- 编程之美 set 10 队列中取最大值操作问题
- [LeetCode] Sliding Window Maximum 滑动窗口最大值
- POJ 2823 (从经典滑动窗口最大值问题入门单调队列)
- Leetcode编程练习二:求直方图中矩形最大面积
- 编程之美 队列中取最大值操作
- 编程之美-队列中取最大值操作问题