众所周知,《剑指offer》是一本“好书”。html
为何这么说?java
由于在技术面试中,它里面罗列的算法题在面试中出现的频率是很是很是高的。git
有多高,以我目前很少的面试来看,在全部遇到的面试算法题中,出现原题的几率大概能有6成,若是把基于原题的变种题目算上,那么这个出现几率能到达9成,10题中9题见过。github
至于为何给“好书”这两个字打引号,由于这本书成了面试官的必备,若是考生不会这本书上的题目,就极可能获得面试官负面的评价。这本书快要成为评判学生算法能力的惟一标准,这使得考前突击变成了一个惯例,反而让投机倒把成了必要,并不必定能真正的考察考生的算法能力。面试
对于剑指offer题解这个系列,个人写文章思路是,对于看了文章的读者,可以:算法
快速找到个人《剑指offer题解》专栏:后端
剑指offer面试题59题数组
给定一个数组和滑动窗口的大小,找出全部滑动窗口里数值的最大值。例如,若是输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有如下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。安全
扫描窗口k,获得最大值。对于长度为n的数组,算法时间复杂度O(nk)bash
显然不是最优解。
面试题30中,咱们实现过用两个栈实现了队列,能够在O(1)时间获得栈的最大值,也就能够获得队列的最大值。
这样总的时间复杂度O(n)
可是这样的思路写代码,等于同时要写两个题目,面试时间可能不容许。
参考解释:
数组的第一个数字是2,把它存入队列中。第二个数字是3,比2大,因此2不多是滑动窗口中的最大值,所以把2从队列里删除,再把3存入队列中。第三个数字是4,比3大,一样的删3存4。此时滑动窗口中已经有3个数字,而它的最大值4位于队列的头部。
第四个数字2比4小,可是当4滑出以后它仍是有可能成为最大值的,因此咱们把2存入队列的尾部。下一个数字是6,比4和2都大,删4和2,存6。就这样依次进行,最大值永远位于队列的头部。
可是咱们怎样判断滑动窗口是否包括一个数字?应该在队列里存入数字在数组里的下标,而不是数值。当一个数字的下标与当前处理的数字的下标之差大于或者相等于滑动窗口大小时,这个数字已经从窗口中滑出,能够从队列头部把它删除。所以,咱们既有可能从头部删除数字,又可能从尾部删除数字,因此要双端队列。
注意点:
ArrayDeque的几个API:pollFirst、peekFirst等
ArrayDeque保存的是下标
最新的数的下标是一定加进去的。
import java.util.ArrayList;
import java.util.ArrayDeque;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> result = new ArrayList<>();
// 排除特殊状况,窗口的长度为0
if (size==0) return result;
// 滑动窗口最左边数的index
int begin;
// 创建一个双端队列
ArrayDeque<Integer> q = new ArrayDeque<>();
for(int i=0;i<num.length;i++){
// begin是窗口起始位置
begin = i-size+1;
// 队列空,直接加入
if(q.isEmpty())
q.add(i);
// 若队列最左边值已经不在窗口内,直接删除
else if(begin > q.peekFirst())
q.pollFirst();
// 从队尾开始比较,把全部比他小的值丢掉
while((!q.isEmpty()) && num[q.peekLast()] <= num[i])
q.pollLast();
// 随后再把它放进去
q.add(i);
// 若窗口起始位置在数组的0位置上或者以后(窗口是完整大小的),才计算窗口的有效最大值
if(begin>=0){
// 永远是队列最左边最大,加入结果集
result.add(num[q.peekFirst()]);
}
}
return result;
}
}
复制代码
采用双端队列,很是巧妙地一题。
我目前是一名后端开发工程师。技术领域主要关注后端开发,数据爬虫,数据安全,5G,物联网等方向。
微信:yangzd1102
Github:@qqxx6661
我的博客:
若是文章对你有帮助,不妨收藏起来并转发给您的朋友们~