滑动窗口法算法(matlab、java)

这是第一次写博文,想加强自己对于这方面知识点的理解,虽然算法很简单,但是想把自己想法写下来。

正好看到《剑指offer题目》面试题65:滑动窗口的最大值

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

{[2,3,4],2,6,2,5,1}中[2,3,4]三个数最大是4,{2,[3,4,2],6,2,5,1}中[3,4,2]三个数最大是2, {2,3,[4,2,6],2,5,1}中[4,2,6]三个数最大是6, {2,3,4,[2,6,2],5,1}中[2,6,2]三个数最大是6, {2,3,4,2,[6,2,5],1}中[6,2,5]三个数最大是6,{2,3,4,2,6,[2,5,1]}中[2,5,1]三个数最大是5。所以最后滑动窗口的最大值数组为:{4,4,6,6,6,5}。

下面先展示matlab代码段:

clc;
clear;

a=[2,3,4,2,6,2,5,1];    % a是数组
w=3;                               % w是滑动窗口的大小3
len=length(a);                     % len表示矩阵长度

n=1;
c=[];
q=1;
    for i=n:len-w+1
        b=[a(i),a(i+1),a(i+2)];
        d=max(b);
        c(q)=d;
        q=q+1;
        n=n+1;
    end  
c

 

java代码段:

SlideWindow代码块:

package cn.itcast_06;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
 
/**
 * 返回一个n-w+1 长度的数组, 每个元素代表每个窗口中的最大值。
 */
public class SlideWindow {
 
    /**
     * array:源数组
     * w:窗口大小
     * 时间复杂度O(N*w)
     */
    public int[] moveWindow(int[] array, int w) {
 
        int[] result = new int[array.length - w + 1];
 
        for (int i = 0; (i + (w - 1)) < array.length; i++) {
 
            int[] newArr = Arrays.copyOfRange(array, i, i + w);
            Arrays.sort(newArr); // 左闭右开
            result[i] = newArr[w - 1];
        }
        return result;
    }
    /**
     * 最优解: 时间复杂度为O(N)
     * 利用双端队列
     */
    public Integer[] moveWindow1(Integer[] arr,int n, int w) {
         
        if(w == 1){
            return arr;   //如果窗口大小为1, 直接返回数组即可
        }
        Deque<Integer> deq = new LinkedList<>();  //双端队列
         
        List<Integer> res = new ArrayList<>();
         
        for(int i=0; i<n; i++){
             
            //如果qmax为空,或者取出当前deque队尾存放的下标j 满足 arr[j] > array[i],
            //直接把下标i放进deque的队尾.
            if(deq.isEmpty() || arr[deq.getLast()] > arr[i]){
                deq.addLast(i);
            }else{
                //如果arr[j] <= array[i],则一直从deque的队尾弹出下标。
                //直到某个下标在deque中对应的值大于arr[i],就把i放入deque的队尾。
                while(!deq.isEmpty() && arr[deq.getLast()] <= arr[i]){
                    deq.removeLast();
                }
                deq.addLast(i);
            }
            //如果deque队头的下标等于i-w,弹出deque当前队头下标.
            if(deq.getFirst() == i-w){
                deq.removeFirst();
            }
            //如果w窗口等于3的话,那么从i=2开始,产生的才是窗口的最大值。
            if(i < w-1){
                continue;
            }
            res.add(arr[deq.getFirst()]);
        }
        return (Integer[])res.toArray(new Integer[n-w+1]);
    }
 

}

主程序代码块:

package cn.itcast_06;

import java.lang.reflect.Array;

public class main {
	public static void main(String[] args) {
		SlideWindow mw = new SlideWindow();
		Integer[] array = new Integer[] { 4, 5, 5, 4, 3, 3, 6, 7, 6, 4, 8, 9, 14 };
		Integer[] window = mw.moveWindow1(array, array.length, 3);
		System.out.print("[");
		for (int x = 0; x < array.length; x++) {
			if (x == array.length - 1) {
				System.out.print(array[x]);
			} else {
				System.out.print(array[x] + ", ");
			}
		}
		System.out.println("]");
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40260642/article/details/82926133