65-滑動窗口

一、題目描述

給定一個數組和滑動窗口大小,請找出所有滑動窗口裏的最大值。
例如,如果輸入數組{2,3,4,2,6,2,5,1}及滑動窗口的大小爲3,那麼一共存在6個滑動窗口,它們的最大值分別爲{4,4,6,6,6,5}

二、解題思路

申請一個windowMax數組,用來存放每一個窗口下的最大值
申請一個兩端開口的隊列,用來保存可能爲滑動窗口中最大值的下標,這個隊列的特點在於:
    1)隊首下標若無更新,則爲當前滑動窗口最大值的下標,將此下標對應的元素加入windowMax數組中;
    2)隊尾元素下標出隊的情況:當即將入隊的下標對應的值大於隊尾元素下標對應的值,則將隊尾元素下標出隊,直到隊尾元素下標對應的值大於即將入隊的下標對應的值將此下標入隊;
    3)隊首元素下標出隊的情況:若之前的滑動窗口最大值已經滑出了窗口但是它的最大值還在隊首,需要講這個隊首元素強制出隊,保證當前滑動窗口下新的最大值;

三、解題算法

/*****************************************************
author:tmw
date:2018-8-29
*****************************************************/
#include <stdio.h>
#include <stdlib.h>

void findMaxInWindow( int array[], int len, int size )
{
    int kk=0;
    /**參數合法性判斷**/
    if( array != NULL && len >= size && size >= 1 )
    {
        /**創建windowMax數組,用來存放每一個窗口的最大值**/
        int windowMax[len];
        for(kk=0; kk<len; kk++)
            windowMax[kk] = 0;

        int wind = 0;//windowMax數組的匹配遊標

        /**創建一個兩端開口的隊列,用來存放當前窗口下可能的最大值**/
        int index[len];
        for(kk=0; kk<len; kk++)
            index[kk] = 0;

        int ii=0; int jj=0; //i爲前遊標;j爲後遊標
        int i=0;

        /**開始以窗口爲size做操作**/
        for( i=0; i<size; i++ )
        {
            /**當隊列非空且即將入隊的元素下標對應的值大於當前隊尾下標對應的值,則將當前下標出隊,如此重複**/
            while( ii!=jj && array[i]>=array[index[jj]] )
                jj--; //相當於尾元素出隊
            index[++jj] = i;
            ii++; //有效元素從第一位開始
        }
        for( i=size; i<len; i++ )
        {
            /**以size爲窗口值的操作已經完成,接下來繼續以size來挪動窗口,並且將當前窗口找到的最大值(隊首元素)放到windowMax數組中**/
            windowMax[wind++] = array[index[ii]]; //將上一個窗口的最大值加入數組,因此循環完後,記得補上將當前最大值加入數組

            /**尾元素出隊**/
            while( ii!=jj+1 && array[i]>=array[index[jj]] )//因爲前面已經約定有效位從第一位開始,當ii==jj時並不表示此隊列爲空,而是ii=jj+1
                jj--; //相當於尾元素出隊
            /**更新首元素**/
            if( ii!=jj+1 && array[index[ii]] <= array[i-size] )
                ii++;
            index[++jj] = i;
        }
        windowMax[wind] = array[index[ii]];

        /**打印檢查**/
        for(i=0; i<len; i++)
            printf("%d ",windowMax[i]);
    }
}

變種1- 窗口size可變,求和大於等於給定值的最小窗口size

【題目描述】給定一個數組array和目標值target,找到連續子陣列的最小長度,使得它們的總和≥target。 如果沒有,則返回INT_MAX。

【解題思路】

設定兩個遊標 start和end 初始位置都爲0,初始化min_len = INT_MAX
1)當[start,end]的sum值小於target時,end++,並將更新後end指向的值加入總和sum
2)當[start,end]的sum值大於等於target時,更新並記錄min_len = min(min_len,end-start),並將當前start指向的元素從sum中減掉,同時start++
3)直到start和end任意一個大於array_len 算法結束

/***********************************************
author:tmw
date:2018-8-30
***********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define min(a,b) (a<b?a:b)
int findMinWindowSize( int* array, int array_len, int target )
{
    if( array == NULL || array_len < 0  ) return INT_MAX;

    int start = 0;
    int end = 0;

    int sum = 0;
    int min_len = INT_MAX;
    while( start < array_len && end < array_len )
    {
        /**當[start,end]的sum值小於target時,end++,並將更新後end指向的值加入總和sum**/
        while( sum < target && end < array_len )
            sum += array[end++];

        /**
            當[start,end]的sum值大於等於target時,更新並記錄min_len = min(min_len,end-start),
            並將當前start指向的元素從sum中減掉,同時start++
        **/
        while( sum >= target && start <= end )
        {
            min_len = min( min_len, end-start );
            sum -= array[start++];
        }
    }
    return min_len;
}

 

                                                                      夢想還是要有的,萬一實現了呢~~~~ヾ(◍°∇°◍)ノ゙~~~~~~~~~~~~~~~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章