1. 程式人生 > >滑動視窗法演算法(matlab、java)

滑動視窗法演算法(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("]");
	}
}