这道题是从优先队列的难题里面找到的一个题目。可是解法并不是优先队列,而是双项队列deque

其实只要知道思路,这一道题直接写没有太大的问题。我们看看题

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。

返回滑动窗口最大值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释: 滑动窗口的位置 最大值
--------------- -----
[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

翻译一下就是: 滑动区间里面每K个最大值

当然暴力naive的解法就显而易见了,用O(n*k)可以解决,不细说。但还是手痒写个伪代码:

for(size_t i=0;i<nums.size();i++){
int maxValue=INT_MIN;
for(size_t j=i;j<i+k;j++){
maxValue=max(maxValue,nums[j]);
}
res.push_back(maxValue);
}

我想到的另一种方法是建立一个最大堆。

想法很简单:每次读入一个新的数字,就把不在区间范围内的数字移除堆里,然后堆的顶部就是此次循环的结果。

一个堆其实非常容易实现。我们甚至可以使用一个C++ STL中的priority_queue。难点就在于,如何把这个不在区间范围内的数字移除。

However

在这里我介绍一种更快更通用的方法,使用双项队列。这里为了效率和快捷使用了deque容器,也可以使用list容器。

我声明了一个变量deque<int>window,用于存储下标。这个变量有以下特点:

  1. 变量的最前端(也就是window.front())是此次遍历的最大值的下标
  2. 当我们遇到新的数时,将新的数和双项队列的末尾(也就是window.back())比较,如果末尾比新数小,则把末尾扔掉,直到该队列的末尾比新数大或者队列为空的时候才停止,做法有点像使用栈进行括号匹配。
  3. 双项队列中的所有值都要在窗口范围内

特点一只是方便我们获取每次窗口滑动一格之后的最大值,我们可以直接通过window.front()获得

通过特点二,可以保证队列里的元素是从头到尾降序的,由于队列里只有窗口内的数,所以他们其实就是窗口内第一大,第二大,第三大...的数。

特点三就是根据题意设置的。但我们实际上只用比较现在的下标和window.front()就可以了,想想为什么?

Answer: 因为只要窗口内第一大元素也就是这个window.front()在窗口内,那我们可以不用管第二大第三大元素在不在区间内了。因为答案一定是这个第一大元素。如果window.front()不在窗口内,则将其弹出,第二个大元素变成第一大元素,第三大元素变成第二大元素以此类推。

代码编写的过程还要时刻检查队列是否为空防止抛出异常。

根据上面这些信息我们就可以编写此题的代码了。

Solution

class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(k==0)return {};
vector<int>res;
deque<size_t>window;
/*Init K integers in the list*/
for (size_t i = 0; i < k; i++) {
while (!window.empty() && nums[i] > nums[window.back()]) {
window.pop_back();
}
window.push_back(i);
}
res.push_back(nums[window.front()]);
/*End of initialization*/
for (size_t i = k; i < nums.size(); i++) {
if (!window.empty() && window.front() <= i - k) {
window.pop_front();
}
while (!window.empty() && nums[i] > nums[window.back()]) {
window.pop_back();
}
window.push_back(i);
res.push_back(nums[window.front()]);
}
return res;
}
};

[Leetcode]双项队列解决滑动窗口最大值难题的更多相关文章

  1. 【Leetcode堆和双端队列】滑动窗口最大值(239)

    题目 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示例: 输入 ...

  2. [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 ...

  3. [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 ...

  4. Leetcode 239.滑动窗口最大值

    滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值. 示例: ...

  5. Java实现 LeetCode 239 滑动窗口最大值

    239. 滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最 ...

  6. LeetCoded第239题题解--滑动窗口最大值

    滑动窗口最大值 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 进 ...

  7. [Swift]LeetCode239. 滑动窗口最大值 | 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 ...

  8. 算法进阶面试题02——BFPRT算法、找出最大/小的K个数、双向队列、生成窗口最大值数组、最大值减最小值小于或等于num的子数组数量、介绍单调栈结构(找出临近的最大数)

    第二课主要介绍第一课余下的BFPRT算法和第二课部分内容 1.BFPRT算法详解与应用 找到第K小或者第K大的数. 普通做法:先通过堆排序然后取,是n*logn的代价. // O(N*logK) pu ...

  9. Q239 滑动窗口最大值

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位. 返回滑动窗口最大值. 示例: 输入: nums ...

随机推荐

  1. DJango 基础 (1)

    django基础 知识点: 基本认知 工具准备 新建项目 目录及文件说明 开发服务器 创建视图函数 新建应用(app) 1.基本认知 Django是用Python开发的一个免费开源的Web框架,可以用 ...

  2. day36 GIL锁与线程池

    多进程与多线程效率对比 # # """ # # 计算密集型 # """ # from threading import Thread # f ...

  3. FortiGate设置E-mail告警

    1.配置邮件服务器 2.配置告警

  4. Java比较两个时间的前后

    public static int compare_date(String DATE1, String DATE2) { DateFormat df = new SimpleDateFormat(&q ...

  5. sbb指令

    sbb是带借位减法指令,它利用了CF位上记录的借位值. 指令格式:sbb 操作对象1,操作对象2 功能:操作对象1=操作对象1-操作对象2-CF 比如指令sbb ax,bx实现的功能是: (ax)=( ...

  6. 二、putty的下载安装和基本使用方法教程

    转载自:https://baijiahao.baidu.com/s?id=1597811787635071952&wfr=spider&for=pc PuTTY是一款开源(Open S ...

  7. centos查看系统版本

    显示系统版本 cat /etc/redhat-release cat /proc/version uname -a 查看位数 file /bin/ls

  8. (O)WEB:前端网站性能优化(原创)

    *从理论.实战编码.实战调试3个方面学习前端性能优化(包括页面加载时间和页面流畅度): -------------------------------理论----------------------- ...

  9. spring rabbitmq集成

    pom.xml加 <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-clien ...

  10. Linux 给文件夹或者文件增加权限

    chmod -R 777 文件夹参数-R是递归的意思777表示开放所有权限 chmod 777 test.sh chmod +x 某文件 如果给所有人添加可执行权限:chmod a+x 文件名:如果给 ...