演算法基礎課 陣列模擬棧 佇列

2021-10-09 06:59:17 字數 3136 閱讀 4596

二、陣列模擬佇列

用陣列模擬棧,可以幫助我們理解棧的本質。

模擬棧的關鍵點就是「棧頂指標」!這比鍊錶簡單多了,鍊錶需要知道頭尾、每個節點的前後指標,而棧只有乙個指標!

隨著不斷地push和pop,棧頂指標會不斷向後移動,前面的空間就浪費了。這對於演算法題來說是可以忍受的,畢竟更看重時間效率。

#include

#include

using

namespace std;

const

int n=

1e6+10;

int m;

int stk[n]

,tt;

//stk模擬棧,tt模擬棧頂指標

void

clear()

void

push

(int x)

void

pop(

)bool

empty()

void

query()

intmain()

else

if(str==

"pop"

)else

if(str==

"query"

)else

if(str==

"empty")}

//【遍歷/依次彈出棧】

while

(tt>-1

)return0;

}

要求:輸出每個數字左邊第乙個比它小的數字。

思路:暴力解法是,對於第i個數,從第i-1個數開始向左遍歷,直到遇到乙個比它小的數。我們可以這樣乙個性質,如果第i個數左邊某個數比它大,那這個數永遠不會被輸出。對於i來說當然不能輸出,對於i以後的數,也不會輸出,所以可以直接刪掉。

基於此,我們可以把陣列中的每個數放入棧裡面,對於新的數,如果棧頂比它大,就彈出。這樣最後得到的就是乙個單調遞增的棧。當然,我們的答案也很容易就出來了。

**模板

#include

using

namespace std;

const

int n=

1e5+10;

int tt=-1

,stk[n]

;int

main()

else cout<

<

<

" ";

stk[

++tt]

=x;}

return0;

}

用陣列模擬佇列,關鍵是「隊頭指標」和「隊尾指標」。隊尾初始化為-1,隨著不斷新增元素,隊尾指標不斷向後移動,就像棧頂指標一樣。而隊頭呢,在新增新元素的時候是不變的,所以一開始就要指向index為0的位置。

如果直接取隊頭的元素,此時佇列可能為空。那怎麼判斷隊列為空呢?直接判斷隊尾指標是否為-1嗎?錯了!要判斷隊尾指標和隊頭指標的關係,隊列為空的時候隊尾》隊頭。

隨著不斷地push、pop,隊尾和隊頭的指標會不斷地後移,前面的空間就浪費了。這對於演算法題來說,是可以忍受的。當然還有迴圈佇列這種解決方式。

#include

#include

using

namespace std;

const

int n=

1e6+10;

int q[n]

,hh=

0,tt=-1

;void

clear()

void

push

(int x)

void

pop(

)void

empty()

bool

isempty()

void

query()

intmain()

else

if(str==

"pop"

)else

if(str==

"query"

)else

if(str==

"empty")}

//【遍歷/依次彈出隊頭元素】

// while(!isempty())

return0;

}

要求:給定乙個大小為n≤106的陣列。有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。您只能在視窗中看到k個數字。每次滑動視窗向右移動乙個位置。您的任務是確定滑動視窗位於每個位置時,視窗中的最大值和最小值。

思路:暴力解法是,維護滑動視窗為乙個普通佇列,每次新增和刪除乙個數,並線性遍歷,得到k個數中的最大值和最小值。然而我們可以這樣乙個性質,如果將乙個新的數新增到滑動視窗中,若這個數左邊某個數比它大,那該數永遠不會被輸出。所以我們可以把滑動視窗中比新的數大的數字都刪掉。

基於此,滑動視窗就變成了乙個單調遞增的佇列。隊頭是最小值,隊尾是最大值。

**模板

【注意】為什麼要進行兩次呢?因為每次只能得到該視窗的一種最值。比如,[1,3,-1],-3。當i==2,指向-1時,我們要求最小值,此時,我們已經把佇列刪的只剩下了。正確的最大值早就被刪掉啦!

#include

using

namespace std;

const

int n=

1e6+10;

int n,k;

int a[n]

,q[n];

//原陣列和滑動視窗佇列

intmain()

//輸出最小值

//<1>定義單調佇列的頭和尾指標

int hh=

0,tt=-1

;//<2>遍歷元素組中的每個元素

for(

int i=

0;i)puts(""

);//輸出最大值

hh=0,tt=-1

;for

(int i=

0;i)puts(""

);return0;

}

演算法基礎課筆記

方法步驟 1 確定分界點。一般取q l q r q l r 2 作為樞紐。2 調整區間,左邊的都是小於等於樞紐值,右邊的都是大於等於樞紐值。最重要 3 遞迴處理左右兩段。快速排序模板 void quick sort int q int l int r quick sort q,l,j quick s...

演算法基礎課 高精度

j高精度演算法 常用的有加減,對於乘除我們只會用小數乘大數。首先對於高精度加法,應該使用string類來進行表示,然後對於此類問題還需要特別注意的就是對於乙個大數來說,我們應該進行倒置,這樣對於加減來說更為有利。對於高精度加法模板如下 應該先設定乙個t 0 然後分別加上每乙個數的對應位即可解決問題。...

演算法基礎課 雙指標演算法

首先對於雙指標演算法,必須明確,對於此問題來說,只能是乙個優化問題,核心思想是把乙個o n2 的時間複雜度問題給優化到o n 來解決。通用模板 按照樸素演算法 for int i 0 i for int j 0 j 按照某種性質進行優化 for int i 0,j 0 i while jcheck ...