日月的弯刀  
Where Amazing Happens!

转载请标明出处http://www.cnblogs.com/haozhengfei/p/a14049ec0869a8125a69f3af37471c77.html 


滑动窗口练习题

 

第8节 滑动窗口练习题

 

有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。 以数组为[4,3,5,4,3,3,6,7],w=3为例。因为第一个窗口[4,3,5]的最大值为5,第二个窗口[3,5,4]的最大值为5,第三个窗口[5,4,3]的最大值为5。第四个窗口[4,3,3]的最大值为4。第五个窗口[3,3,6]的最大值为6。第六个窗口[3,6,7]的最大值为7。所以最终返回[5,5,5,4,6,7]。

给定整形数组arr及它的大小n,同时给定w,请返回res数组。保证w小于等于n,同时保证数组大小小于等于500。

测试样例:
[4,3,5,4,3,3,6,7],8,3
返回:[5,5,5,4,6,7]
 
 
1
import java.util.*;
2

3
public class SlideWindow {
4
    public int[] slide(int[] arr, int n, int w) {
5
        //result数组中保存每个窗口状态下的最大值
6
        int[] result = new int[n-w+1];
7

8
        //记录双端队列队头的下标 ,队尾下标
9
        int[] qmax = new int[n];
10
        int front = 0, back = 0;
11

12
        //j 标记是否达到窗口大小,同时记录result中下一个应该放入的元素的下标
13
        int j = 0;
14

15
        for(int i=0; i<n; i++){
16

17
            while(front < back && arr[qmax[back-1]] < arr[i])//back为当前要往qmax中放入的值
18
                back--;
19
            qmax[back++] = i;
20

21
            if(j+w-1 == i){
22
                //达到窗口长度
23
                result[j] = arr[qmax[front]];
24
                j++;
25
            }
26
            if(qmax[front]+w-1 == i){
27
                //队头过期
28
                front++;
29
            }
30
        } 
31
        return result;
32
    }
33
}
 
 
您的代码已保存
答案正确:恭喜!您提交的程序通过了所有的测试用例
 
 
代码示例
 1 package com.hzf.stack$queue;
 2 
 3 /**
 4  * 有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。
 5  * 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。
 6  * 以数组为[4,3,5,4,3,3,6,7],w=3为例。因为第一个窗口[4
 7  * ,3,5]的最大值为5,第二个窗口[3,5,4]的最大值为5,第三个窗口[5,4,
 8  * 3]的最大值为5。第四个窗口[4,3,3]的最大值为4。第五个窗口[3,3
 9  * ,6]的最大值为6。第六个窗口[3,6,7]的最大值为7。所以最终返回[5,5,5,4,6,7]。
10  * 
11  * 给定整形数组arr及它的大小n,同时给定w,请返回res数组。保证w小于等于n,同时保证数组大小小于等于500。
12  * 
13  * 测试样例: [4,3,5,4,3,3,6,7],8,3 返回:[5,5,5,4,6,7]
14  * 
15  * @author hzf
16  *
17  */
18 public class SlideWindow {
19     public int[] slide(int[] arr, int n, int w) {
20         //result数组中保存每个窗口状态下的最大值
21         int[] result = new int[n-w+1];
22         
23         //记录双端队列队头的下标 ,队尾下标
24         int[] qmax = new int[n];
25         int front = 0, back = 0;
26         
27         //j 标记是否达到窗口大小,同时记录result中下一个应该放入的元素的下标
28         int j = 0;
29         
30         for(int i=0; i<n; i++){
31             
32             while(front < back && arr[qmax[back-1]] < arr[i])//back为当前要往qmax中放入的值
33                 back--;
34             qmax[back++] = i;
35              
36             if(j+w-1 == i){
37                 //达到窗口长度
38                 result[j] = arr[qmax[front]];
39                 j++;
40             }
41             /**
42              * 保证qmax中front所代表的索引不会过期,
43              * 这个索引的边界就是:qmax[front]+w-1 == i,满足这个条件front++,否则下一窗口就会过期
44              * 比如
45              *          front  back
46              *   qmax     6     8
47              *   arr      11    5
48              *   当窗口大小w==3时,假设此时result[j]取arr[qmax[front]],front没有更新,
49              *   如果下一次的arr[9] = 4,那么有如下   
50              *           front      back
51              *   qmax     6     8     9
52              *   arr      11    5     4
53              *   此时如果在上一步中没有更新front,那么此时窗口[7,8,9]的最大值取的是arr[qmax[6]],显然6已经过期
54              *   
55              *   所以综上所述,一旦qmax[front]所代表的索引达到该索引所能控制的边界,front++,以防下一次该front已经过期
56              */
57             if(qmax[front]+w-1 == i){
58                 //队头过期
59                 front++;
60             }    
61         } 
62         return result;
63     }
64 }
View Code

 

posted on 2017-03-18 23:58  日月的弯刀  阅读(15942)  评论(2编辑  收藏  举报