LeetCode题解-----Sliding Window Maximum
题目描述:
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 3
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 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
Therefore, return the max sliding window as [3,3,5,5,6,7].
Note:
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
分析:
开始觉得题目的形式很眼熟,感觉应该用Max Heap解。但是显然Max Heap的复杂度是O(n*logK),事实上应该用类似与插入排序的手法,利用双向队列求解。遍历数组,每遇到一个数就与队列的末尾进行比较,若队列末尾的数小于当前数,则队列末尾退出队列,如此往复,知道队列为空,或者队列里的数都大于当前数,最后插入当前数。由此可知,队列中的数是按照从队首到队尾从大到小排序而成。我们每次将窗口往前移动一格,就插入一个数,并且在队首取得窗口的最大值。不过,这里需要注意一点,队首的数可能已经位于窗口之外了!因此,我们用了一个比较tricky的手法,那就是在队列中插入的并不是具体元素的值,而是元素在数组中的位置,这样我们在遍历数组的过程中就能判断队列中的数是否仍然在队列中了。若我们在取最大值时,发现队首的元素已经在窗口之外了,则将其弹出,直到找到仍在窗口内的队首元素为止。最后,不断循环上述过程,即可得到问题的解。
但是,问题是为什么上面说的解法是O(n)的复杂度呢,插入排序的思想和上面说的是完全一致的,可是复杂度却是O(n*n)。其实我们可以发现,上述解法与插入排序不同的是,不存在重复比较。在插入新元素时,比新元素小的元素都退出队列了,因为它们不可能是之后窗口的解。在取最大值时,所有不再窗口内的元素也全都弹出队列了。最终我们可以发现,每次比较都伴随着插入或者删除元素,而元素个数为n,因此全局的操作最多可能分别只有n次的插入,删除,比较操作,所以复杂度为O(n)。(第一次用双向队列求解问题,感觉还是挺神奇的)
代码:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> d;
vector<int> ans;
if(nums.size()==0) {
return ans;
}
d.push_front(0);
for(int i=1;i<k;i++) {
while(!d.empty()&&nums[d.back()]<nums[i]) {
d.pop_back();
}
d.push_back(i);
}
ans.push_back(nums[d.front()]);
for(int i=k;i<nums.size();i++) {
while(!d.empty()&&nums[d.back()]<nums[i]) {
d.pop_back();
}
d.push_back(i);
while(d.front()<=i-k) {
d.pop_front();
}
ans.push_back(nums[d.front()]);
}
return ans;
}
};
LeetCode题解-----Sliding Window Maximum的更多相关文章
- [LeetCode] 239. Sliding Window Maximum 滑动窗口最大值
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- [leetcode]239. Sliding Window Maximum滑动窗口最大值
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- leetcode 239 Sliding Window Maximum
这题是典型的堆排序算法,只是比一般的堆算法多了删除的操作,有两件事需要做: 1 用一个hash表存储从输入数组索引到堆数组(用于实现堆的那个数组)所以的映射,以便在需要删除一个元素的时候能迅速定位到堆 ...
- [leetcode] #239 Sliding Window Maximum (Hard)
原题链接 题意: 给定一个数组数字,有一个大小为k的滑动窗口,它从数组的最左边移动到最右边.你只能在窗口看到k个数字.每次滑动窗口向右移动一个位置. 记录每一次窗口内的最大值,返回记录的值. 思路: ...
- leetcode面试准备:Sliding Window Maximum
leetcode面试准备:Sliding Window Maximum 1 题目 Given an array nums, there is a sliding window of size k wh ...
- 【LeetCode】239. Sliding Window Maximum
Sliding Window Maximum Given an array nums, there is a sliding window of size k which is moving fr ...
- 【刷题-LeetCode】239. Sliding Window Maximum
Sliding Window Maximum Given an array nums, there is a sliding window of size k which is moving from ...
- [LeetCode] Sliding Window Maximum 滑动窗口最大值
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- Leetcode: sliding window maximum
August 7, 2015 周日玩这个算法, 看到Javascript Array模拟Deque, 非常喜欢, 想用C#数组也模拟; 看有什么新的经历. 试了四五种方法, 花时间研究C# Sorte ...
随机推荐
- ASP.NET MVC5+EF6+EasyUI 后台管理系统--系统权限全套完整图
根据角色或用户或模块查询权限.
- linux2.6 内存管理——逻辑地址转换为线性地址(逻辑地址、线性地址、物理地址、虚拟地址)
Linux系统中的物理存储空间和虚拟存储空间的地址范围分别都是从0x00000000到0xFFFFFFFF,共4GB,但物理存储空间与虚拟存储空间布局完全不同.Linux运行在虚拟存储空间,并负责把系 ...
- PHP资源列表
一个PHP资源列表,内容包括:库.框架.模板.安全.代码分析.日志.第三方库.配置工具.Web 工具.书籍.电子书.经典博文等等. 初始翻译信息来自:<推荐!国外程序员整理的 PHP 资源大全& ...
- Android面试经验 -- 乐视
此次投的是三年经验的Android开发,最后反而因为自己的失误,没有准备充分而导致结果很悲剧,以此告诫自己千万不能疏忽大意. 面试过程 第一次去大公司面试,心里不是一般的激动和紧张,来到乐视大厦门口, ...
- Android5.0以下出现NoClassDefFoundError
事发起因 大周末的,突然接到老大的电话说很多用户无法安装新上线的APK,让我紧急Fix(现Android项目就我一己之力).但奇怪的是也没有Bug Reporter,而且开发过程中也一直没问题.根据上 ...
- 连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法
本文出处:http://www.cnblogs.com/wy123/p/6110349.html 之前遇到过这么一种情况: 连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持 ...
- Scrapy:为spider指定pipeline
当一个Scrapy项目中有多个spider去爬取多个网站时,往往需要多个pipeline,这时就需要为每个spider指定其对应的pipeline. [通过程序来运行spider],可以通过修改配置s ...
- Xamarin Android 之起始篇
序言: 在博客园注册了已经有2年多了,快三年了.从开始学习这一行开始就在博客园注册了这个账号.至今也还没有写过一篇随笔,大多时候都是在园子里头潜水,看大牛写的文章,学习. 写博客不为啥,就是自己对自己 ...
- PHP如何实现网址伪静态
Apache的 mod_rewrite是比较强大的,在进行网站建设时,可以通过这个模块来实现伪静态. 主要步骤如下: 1.检测Apache是否开启mod_rewrite功能 可以通过php提供 ...
- OS存储管理——FIFO,LRU,OPT命中率
课程设计课题 存储管理程序设计 摘 要 虚拟存储器作为现代操作系统中存储管理的一项重要技术,实现了内存扩充功能.而分页请求分页系统正好可以完美的支持虚拟存储器功能,它具有请求调页功能和页面置换功能.在 ...