棧與佇列 移動視窗生成最大值的陣列

2021-08-26 05:56:42 字數 3394 閱讀 2761

有乙個整數型陣列arr和乙個大小為w的視窗從陣列的最左端滑到最右端,視窗每次向右滑動乙個位置。就像是乙個滑動的指標,從頭指向尾,然後輸出視窗中資料的最大值。

例如,一組資料為arr  = [4,3,5,4,3,3,6,7],視窗大小為w = 3時:

[  4    3    5  ]  4    3    3    6    7                           視窗中最大值為 5

4  [  3    5    4  ]  3    3    6    7                           視窗中最大值為 5  

4    3  [  5    4    3  ]  3    6    7                           視窗中最大值為 5

4    3    5  [  4    3    3  ]  6    7                           視窗中最大值為 5

4    3    5    4  [  3    3    6  ]  7                           視窗中最大值為 5

4    3    5    4    3  [  3    6    7  ]                         視窗中最大值為 5

如果陣列的長度為n,視窗大小為w,這一共產生n-w-7個視窗的最大值。

要求:請實現乙個函式。

輸入:整型陣列arr,視窗大小為w

輸出:乙個長度為n-w-1的輸入res,res[ i ]表達每一種視窗狀態下的最大值。.

如果資料長度為n,視窗大小為w,如果做出時間複雜度o(n*w)的解法是不能讓面試官滿意的,本題要求面試者想出的時間複雜度o(n)的實現。所以本題的關鍵在於利用雙端佇列來實現視窗最大值的更新。首先生成的是雙端佇列qmax,qmax中存放著陣列arr中的下標。

假設:遍歷到arr[i],qmax的放入規則為:

1、如果qmax為空,直接把下標i放入qmax,放入過程結束。

2、如果qmax不為空,取出當前qmax隊尾放入隊尾存放的下標,假設為j。

1)如果arr[j] > arr[i],直接把下標i放入qmax的隊尾,放入過程結束。

2)如果arr[j] < arr[i],把j從qmax中彈出,繼續qmax的放入規則。

假設遍歷到arr[i],qmax的彈出規則為:

如果qmax隊頭的下標等於i-w,說明當前qmax隊頭下標已經過期,彈出當前對頭下標即可。根據如上的放入的彈出規則,qmax便成了乙個維護視窗為w的子陣列的最大值更新的結構。舉例如下;

1、開始時qmax為空,qmax={}

2、遍歷到arr[0] == 4,將下標0放入qmax,qmax= 。

3、遍歷到arr[1] == 3,當前qmax的隊尾下標為0,又有arr[0] > arr[1],所以將下標1放入qmax尾部,qmax=。

4、遍歷到arr[2] == 5,當前qmax的隊尾下標為1,又有arr[1] <= arr[2],所以將下標1從qmax的尾部彈出,qmax變成。當前qmax的隊尾下標為0,又有arr[0] <= arr[2],所以將下標0從qmax尾部彈出,qmax變成{}。將下標2放入qmax,qmax=。此時已經遍歷到下標2的位置,視窗arr[0,2]出現,當前qmax對頭的下標為2,所以視窗arr[0,2]的最大值為arr[2](即為5)。

5、遍歷到arr[3]==4,當前qmax的隊尾下標為2,又有arr[2]>arr[3],所以將下標了放入qmax尾部,qmax=。 視窗arr[1..3]出現,  當前qmax隊頭的下標為2,這個下標還沒有過期,所以視窗ar[1..3]的最大值為arr[2] (即5)。

6、遍歷到arr[4]== =3,當前qmax的隊尾下標為3,  又有arr[3]>arr[4], 所以將下標4放入qmax尾部,qmax=。 視窗arr[2..4]出現,當前qmax隊頭的下標為2,這個下標還沒有過期,所以視窗arr[2..4]的最大值為arr[2] (即5)。

7、遍歷到arr[5]==3,當前qmax的隊尾下標為4,  又有arr[4]<= =arr[5],所以將下標4從qmax的尾部彈出,qmax變為。當前qmax的隊尾下標為了,又有arr[3]>arr[5],所以將下標5放入qmax尾部,qmax= 。視窗arr[3..5]出現,當前qmax隊頭的下標為2,這個下標已經過期,所以從qmax的頭部彈出,  qmax變為。當前qmax隊頭的下標為3,這個下標沒有過期,所以視窗arr[3..5]的最大值為arr[3] (即4)。

8、遍歷到arr[6]==6, 當前qmax的隊尾下標為5,又有arr[5]<=arr[6], 所以將下標5從qmax的尾部彈出,qmax變為。當前qmax的隊尾下標為3,  又有arr[3]<=arr[6],所以將下標3從qmax的尾部彈出,qmax變為{}。將下標6放入qmax,qmax=。視窗ar([..]出現,當前qmax隊頭的下標為6,這個下標沒有過期,所以視窗arr[4..6]的 最大值為arr[6](即6)。

9、 遍歷到arr[7]==7, 當前qmax的隊尾下標為6,又有arr[6]<=arr[7], 所以將下標6 從qmax的尾部彈出,qmax 變為{}。將下標7放入qmax,qmax=。 視窗arr[5..7]出現,當前  qmax隊頭的下標為7,這個下標沒有過期,所以視窗arr[5..7]的最 大值為arr[7](即7)。

10、依次出現的視窗最大值為[5,5,5,4,6,7],在遍歷過程中收集起來,最後返回即可。

具體過程參看如下**中的getmax window方法。

// 移動視窗獲取最大值方法

public int getmaxwindow(int arr,int w)

// 例項化乙個鍊錶結構

linkedlistqmax = new linkedlist();

// 例項化乙個int型別陣列並且定義長度為執行的次數

int res = new int[arr.length - w + 1];

// 定義乙個下標常量

int index = 0;

// 迴圈遍歷陣列

for (int i = 0 ; i < arr.length ; i++)

// 隊尾新增最後乙個元素

qmax.addlast(i);

// 判斷對頭元素時候為最後乙個元素

if (qmax.peekfirst() == i - w)

// 如果移動到最後元素前

if (i >= w - 1)

} // 返回資訊的集合

return res;

}

雙端佇列,將arr中的元素加入res該佇列中,若該佇列的隊尾元素小於等於要加入的元素,則不斷的彈出,直到隊尾元素大於該元素或者隊列為空。此時將該元素的序號加入佇列中。同時當 i-w == 隊頭的序號,則將隊頭元素彈出。上述過程中,  每個下標值最多進qmax-一次,  出qmax一-次。所以遍歷的過程中進出雙端佇列的操作是時間複雜度為o(n),整體的時間複雜度也為o(n)。寫完手工。。睡覺

棧和佇列 生成視窗最大值陣列

題目 有乙個整型陣列arr和乙個大小為w的視窗從陣列的最左邊滑到最右邊,視窗每次向右滑動乙個位置。例如,陣列為 4,3,5,4,3,3,6,7 視窗大小為3時 依次出現的視窗為 4,3,5 3,5,4 5,4,3 4,3,3 3,3,6 3,6,7 如果陣列長度是n,視窗大小是w,則一共產生n w ...

棧與佇列 單調佇列解決滑動視窗最大值

設計單調佇列的時候,pop,和push操作要保持如下規則 pop value 如果視窗移除的元素value等於單調佇列的出口元素,那麼佇列彈出元素,否則不用任何操作 push value 如果push的元素value大於入口元素的數值,那麼就將佇列入口的元素彈出,直到push元素的數值小於等於佇列入...

生成視窗最大值

生成視窗最大值陣列 題目 有乙個整型陣列arr和乙個大小為w的視窗從陣列的最左邊滑到最右邊,視窗每次 向右邊滑乙個位置。例如,陣列為 4,3,5,4,3,3,6,7 視窗大小為3時 4 3 5 4 3 3 6 7 視窗中最大值為5 4 3 5 4 3 3 6 7 視窗中最大值為5 4 3 5 4 3...