二、陣列模擬佇列
用陣列模擬棧,可以幫助我們理解棧的本質。
模擬棧的關鍵點就是「棧頂指標」!這比鍊錶簡單多了,鍊錶需要知道頭尾、每個節點的前後指標,而棧只有乙個指標!
隨著不斷地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 ...