LeetCode 239:滑动窗口最大值 思考分析

给定一个数组 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

提示:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length

暴力求解:超时

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int maxnum=-10001;vector<int> result;int n= nums.size();//1、如果k> = nums.size,   if(k>=n){for(int i=0;i<n;i++){if(nums[i]>=maxnum) maxnum=nums[i];}result.push_back(maxnum);return result;}//2、如果k<nums.sizeelse{int left=0;int right=0;for(left = 0;left<=n-k;left++){//更新左右边界right=left+k-1;//更新最小值maxnum=-10001;for(int x=left;x<=right;x++){if(nums[x]>=maxnum) maxnum=nums[x]; }result.push_back(maxnum);}return result;}}
};

优化思路:
可以想到暴力方法肯定是有时间浪费的,在滑窗移动的时候,滑窗内插入一个新值,消失了一个旧值,有k-1个值仍然保留着。
我们只需要比较一下新插入的值和旧的k-1个值中的最大值,将得到的最大值赋给结果数组就可以了。
一开始我想的是用两个容量为2的数组,分别存放第一大的数值和它的下标,第二大的数值和它的下标,但是在推导的时候发现一个问题:
错误代码,具体疑问见代码注释:

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int maxnum[2]={-10001,-10001};      //存储当前滑窗内第一大和第二大的数值int index[2]={0,0};                 //存储当前滑窗内第一大和第二大的数值的下标vector<int> result;int n= nums.size();if(k*n==0) return result;//1、如果k> = nums.size,   if(k>=n){for(int i=0;i<n;i++){if(nums[i]>=maxnum[0]) maxnum[0]=nums[i];}result.push_back(maxnum[0]);return result;}//2、如果k<nums.sizeelse{int left=0;int right=0;//将前k个数进行装载for(int i=0;i<k;i++){//nums[i]比第一大还大,更新第一大if(nums[i]>=maxnum[0]){maxnum[0]=nums[i];   //第一大装载完毕index[0]=i;  } //第二大的范围:大于等于旧的第二大,小于等于新的第一大,并且不能是第一大的数if(nums[i]>=maxnum[1] && nums[i]<=maxnum[0] && index[0]!=i){maxnum[1]=nums[i];   //第二大装载完毕index[1]=i;  }}left=1;//从第k+1个数开始for(right = k;right<n;right++,left++)  {//如果移动的时候将最大值抛弃if(index[0]<left){//比较第二大的值和新插入的值的大小,获取最大值//如果第二大值比新插入值大,则第二大值变为最大值,但是新插入的值不一定是第二大值//所以我们需要构建一个从大到小排列的双端队列!if(maxnum[1]>=)}result.push_back(maxnum);}return result;}}
};

发现需要构建一个从大到小排列的双端队列
1、新的数入队列,并按照其大小排列,然后将比它小的数全部出队列(因为我们需要的是最大值,只要队列中有数比新入队列的数要小就说明它们绝对不可能是最大值,最大值最起码也是大于等于新入队列的数)。
2、观察队首(数值最大)的索引值是否在[left,right]之间,如果不在就出队列,直到队首索引值满足在[left,right]之间

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> result;int n= nums.size();if(n==0 ||k==0) return result;if(k>=n){auto maxPosition = max_element(nums.begin(), nums.end());result.push_back(*maxPosition);return result;}//2、如果k<nums.sizeelse{int left=0;int right=0;// 双向队列 保存当前窗口最大值的数组位置 保证队列中数组位置的数值按从大到小排序deque< int> Dq;// 遍历nums数组for(int i = 0;i < n;i++){// 保证从大到小 如果前面数小则需要依次弹出,直至满足要求//如果队尾的元素小于Nums[i],队尾元素出队列while(Dq.size() && nums[Dq.back()] <= nums[i]){Dq.pop_back();}// 将当前数组下标入队列Dq.push_back(i);if(i>=k-1){// 判断当前队列中队首是否有效,如果队首小于左边界,则将队首出队列,直到队首元素符合要求while(Dq.size() && Dq.front() <= i-k){Dq.pop_front(); }result.push_back(nums[Dq.front()]);}}return result;}}
};

虽然AC了,但是效率不高,不过基本思路是符合大众的:
在这里插入图片描述
不过上述的写法仍然有些不简洁,这里贴一下比较简洁的写法:
https://leetcode-cn.com/problems/sliding-window-maximum/solution/dan-diao-dui-lie-by-labuladong/
官方给出的dp思路,还得理解理解
https://leetcode-cn.com/problems/sliding-window-maximum/submissions/

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int n = nums.size();vector<int> output(n-k+1,0);vector<int> left(n,0);vector<int> right(n,0);left[0]=nums[0];right[n-1]=nums[n-1];for(int i = 1;i<n;i++){if(i%k == 0) left[i]=nums[i];else left[i]=max(left[i-1],nums[i]);int j = n-i-1;if((j+1)%k == 0) right[j]=nums[j];else right[j]=max(right[j+1],nums[j]);}for(int i = 0;i < n-k+1;i++)output[i] = max(left[i+k-1],right[i]);return output;}
};

为什么:两数组一起可以提供两个块内元素的全部信息。
考虑从下标 i 到下标 j的滑动窗口。 根据定义,right[i] 是左侧块内的最大元素, left[j] 是右侧块内的最大元素。因此滑动窗口中的最大元素为 max(right[i], left[j])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机论文范文1500,电子商务毕业论文范文1500字

电子商务毕业论文范文1500字时间稍纵即逝&#xff0c;充满意义的大学生活即将结束&#xff0c;毕业前要通过最后的毕业论文&#xff0c;毕业论文是一种有计划的检验学生学习成果的形式&#xff0c;那么问题来了&#xff0c;毕业论文应该怎么写&#xff1f;下面是小编为大家整理…

为什么要使用反射机制

1、反射的构造过程 直接构造 1、加载程序集 2、根据类名构造 反射构造 1、加载程序集 2、查找需要构造类的类名 3、根据类名构造 注意&#xff1a; 能不用反射还是别用反射,因为毕竟要以性能做为代价, 不过在某些特定场合,还是只能用它,所以要自己根据实际情况来…

java uuid静态方法_Java UUID timestamp()方法与示例

java uuid静态方法UUID类timestamp()方法 (UUID Class timestamp() method) timestamp() method is available in java.util package. timestamp()方法在java.util包中可用。 timestamp() method is used to return the timestamp linked with this UUID. timestamp()方法用于返…

ANT:编译SWC

编译SWC使用的是compc任务&#xff0c;compc需要几个重要的参数&#xff1a; 1、输出路径 2、包含的类 3、源路径 其中第2个参数是比较难拿到的&#xff0c;需要使用ANT的几个其他的方法来将路径转换了类的完整路径&#xff0c;先看完整的代码&#xff1a; <target name&quo…

ssm整合事务失效

<!-- 开启注解驱动的事务管理 --><tx:annotation-driven transaction-manager"transactionManager"/>原因&#xff1a;未开启spring事务驱动

五、规则组织的衍生组织——纬山形组织数学模型的建立

基础概念公式推到可参考该专栏下的前几篇博文。 纬山形组织图&#xff1a; 观察可知&#xff1a;纬山形组织图下半部分是右斜组织&#xff0c;上半部分是左斜组织。右斜和左斜按照垂直方向进行排列。 该图是一个2上3下2上1下(从最下面一行从左往右观看) 特点&#xff1a;每一…

批处理设置计算机不休眠,虚拟机状态下怎样设置电脑不休眠

签中&#xff0c;在“启用休眠”项打勾即可启用休眠功能。如果此项不可用&#xff0c;则说明你的电源不支持休眠功能。或如果你安装了还原精灵等一些保护软件&#xff0c;也无法启用休眠功能。2 打开电脑的休眠功能后&#xff0c;在“电源选项”的“电源使用方案”标签中&#…

HDU 2836 Traversal 简单DP + 树状数组

题意&#xff1a;给你一个序列&#xff0c;问相邻两数高度差绝对值小于等于H的子序列有多少个。 dp[i]表示以i为结尾的子序列有多少&#xff0c;易知状态转移方程为&#xff1a;dp[i] sum( dp[j] ) 1;( abs( height[i] - height[j] ) < H ) 由abs( height[i] - height[j] …

剑指 Offer 57 - II. 和为s的连续正数序列 思考分析

输入一个正整数 target &#xff0c;输出所有和为 target 的连续正整数序列&#xff08;至少含有两个数&#xff09;。 序列内的数字由小到大排列&#xff0c;不同序列按照首个数字从小到大排列。 示例 1&#xff1a; 输入&#xff1a;target 9 输出&#xff1a;[[2,3,4],[4…

java uuid静态方法_Java UUID compareTo()方法与示例

java uuid静态方法UUID类compareTo()方法 (UUID Class compareTo() method) compareTo() method is available in java.util package. compareTo()方法在java.util包中可用。 compareTo() method is used to compare two UUID objects or in other words, it is used to compar…

hdu 1214

找规律的题目。如果不是圆环形状的话&#xff08;也就是n个人排成直线&#xff09;&#xff0c;完全调换顺序需要(n-1)*n/2次交换&#xff1b;为环形的时候&#xff0c;可能不需要这么多&#xff0c;因为调换有了两个方向。我们记直线时n个人需要的交换次数为g(n)(n-1)*n/2&…

六、规则组织的衍生组织——纬向破斜组织数学模型的建立

基础概念公式推到可参考该专栏下的前几篇博文。 纬向破斜组织图&#xff1a; 下半部分(从左往右)&#xff1a;&#xff0c;3上2下2上1下&#xff0c;右斜&#xff0c;飞数为1 上半部分(从下往上)&#xff1a;&#xff0c;2上2下1上3下。左斜&#xff0c;飞数为-1 通过分析可…

车牌识别与计算机编程,基于MATLAB的车牌识别程序详解.ppt

基于MATLAB的车牌识别程序详解自定义一个字符函数&#xff0c;用来从车牌区域中提取出7个字符&#xff0c;其中利用切割函数来进行切割。 程序&#xff1a;function [word,result]getword(d) word[];flag0;y18;y20.5; while flag0 [m,n]size(d);%将d的尺寸存入m n wide0; while…

数据结构与算法2——数组

数组是应用最广泛的数据存储结构。它被植入到大部分编程语言中。大部分数据结构都有最基本的四个操作&#xff1a;插入、删除、查找、修改。对于这四种操作每一种数据结构都有相应的算法。算法和数据结构因此就是非常紧密的相联系的。 1 数组例子 …

java treemap_Java TreeMap putAll()方法与示例

java treemapTreeMap类putAll()方法 (TreeMap Class putAll() method) putAll() method is available in java.util package. putAll()方法在java.util包中可用。 putAll() method is used to copy all the key-value pairs from the given map (m) and paste it into this map…

LeetCode 167. 两数之和 II - 输入有序数组 思考分析

目录1、暴力&#xff0c;超时2、双指针滑动窗口条件限制 AC3、观看题解&#xff08;吸取他人经验&#xff09;1、二分查找2、双指针3、双指针二分查找给定一个已按照升序排列 的有序数组&#xff0c;找到两个数使得它们相加之和等于目标数。 函数应该返回这两个下标值 index1 …

敏捷开发用户故事系列之七:用户故事与MVC

这是用户故事系列的第七篇。&#xff08;之一&#xff0c;之二&#xff0c;之三&#xff0c;之四&#xff0c;之五&#xff0c;之六&#xff0c;之七&#xff0c;之八&#xff0c;之九&#xff09;用户故事和MVC没有关系&#xff0c;因为MVC是实现方法&#xff0c;因此在思考用…

七、规则组织的衍生组织——菱形斜纹组织数学模型的建立

基础概念公式推到可参考该专栏下的前几篇博文。 菱形斜纹组织图&#xff1a; 分析&#xff1a;首先3上2下2上1下&#xff0c;飞数为1&#xff0c;右斜。kw8表示从左下角开始往上数8格为纬峰所在位置&#xff1b;kj8表示从左上角开始往右数8格为经峰所在位置。 这样就将菱形斜…

显卡测试软件毛毛虫,超龙超龙,与众不同,顶流配备,散热一流,3070Ti超龙旗舰版评测...

可能大家都没想到此次显卡荒会持续近一年&#xff0c;还是出现国家级干涉才将这股“歪风”刹住了。而且也仅仅算是刹住了大陆的速度&#xff0c;主要踩死刹车的应该就是黄大厨。他从5月初推出的新核心就采取了出厂即锁算力的做法&#xff0c;但是即便如此&#xff0c;那些看着高…

poj 2513 Colored Sticks

// 判断图是否联通 在连通的基础上还要判断是否存在欧拉通路// 判断连通就并查集了 判断是否存在欧拉通路&#xff1a; 点度数为数的点 1 >3就是不存在的 其它是存在的// 我开始用 map 判重 然后就悲剧了一上午 好久没写 Trie树了 都忘了、#include <iostream> #in…