您的位置:首页 > Web前端

剑指offer之65 滑动窗口的最大值问题

2015-11-07 22:39 387 查看
题目描述如下:

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。

题目分析:

这个题有两个解法,首先使用比较暴力的方法,遍历整个数组,用O(n)时间复杂度的算法找到每一个窗口的最大值,这个方法比较简单就不多做叙述,时间复杂度也非常高;第二个解法是利用队列的思想来实现,主要思想如下:滑动窗口,在队列中记录数据的下标(为什么是下标?),那题目给出的测试用例来说数组{2,3,4,2,6,2,5,1}以及滑动窗口的大小为3,很明显第一个滑动窗口为【2,3,4】,这样很容易看出最大值为4,怎么来算呢,首先把2的下标放在队列中,读入3,判断3比2要大,这样2的存在就没有意义了,把2的下标出队,把3的下标入队;读入4,可以看出4比3要大,3的存在也就没有了意义,把4的下标放入队列中;此时滑动窗口是满的(因为我们读了3个数,下标队列跟滑动窗口不是一个概念);然后我们开始向后滑动窗口,我们需要做的是每次读入一个下标对应的数字要保证队列的下标中左边对应的数字没有比这个数字小的值,因为比这个数小的数肯定不是最大值;这样的话我们随时保证了队列的最左边(队头)的下标对应了此时的最大值;另外还需要注意的是,随着窗口滑动,最大值可能走到了滑动窗口外,这样我们只需要判断改最大值的下标是否在滑动窗口外即可,这也是队列中保存下标的意义所在。根据上述思想,就可以写代码了:

import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
public class Solution65 {

public static void main(String[] args) {
int num[] = {2,3,4,2,6,2,5,1};
ArrayList<Integer> list = maxInWindows(num,3);
for(int i:list){
System.out.println(i);
}

}
public static ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> Window_max = new ArrayList<Integer>();
//创建一个队列
Deque<Integer> index = new LinkedList<Integer>();
//先把窗口填满,填满以后,index中存放了窗口中的最大数
for(int i = 0; i<size; i++){
while(!index.isEmpty() && num[i] >= num[index.getLast()]){
index.removeLast();
}
index.addLast(i);
}
//窗口填满以后开始向右移动窗口
for(int i=size; i<num.length; i++){
//加入新元素以前先把上一个窗口中最大数添加到Window_max中
Window_max.add(num[index.getFirst()]);
//然后窗口滑动一步,比较num[i]和index中下标对应的数,index中First对应的数字是当前最大值
while(!index.isEmpty() && num[i] >= num[index.getLast()]){
index.removeLast();
}
//另外,需要删除已经不在当前窗口的数字对应的下标
if(!index.isEmpty() && index.getFirst()<=(i-size))
index.removeFirst();
//把需要添加最新的数字进index队列
index.addLast(i);
//这样就能保证当前窗口中最大的值为index的First;
}
//把最后一个窗口的最大值加入Window_max,因为上面的每一步加入的都是上一个窗口的最大值。
Window_max.add(num[index.getFirst()]);
return Window_max;

}

}


关键步骤在代码中已经做了注释,

OJ系统如下:点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: