資料結構 高效獲取最大值的棧和佇列

2021-06-23 04:49:09 字數 1650 閱讀 4730

這道題是在清華大學鄧俊輝老師的資料結構上碰到的,原題如下:

描述現有一條單向單車道隧道,每一輛車從隧道的一端駛入,另一端駛出,不允許超車

該隧道對車輛的高度有一定限制,在任意時刻,管理員希望知道此時隧道中最高車輛的高度是多少 現在請你維護這條隧道的車輛進出記錄,並支援查詢最高車輛的功能

輸入第一行僅含乙個整數,即高度查詢和車輛出入操作的總次數n 以下n行,依次這n次操作。各行的格式為以下幾種之一:

輸出若d和m操作共計m次,則輸出m行 對於每次d操作,輸出離開隧道車輛的高度 對於每次m操作,輸出所查詢到的最大高度

題目看上去很簡單,只需要擴充套件一下stl中的queue,增加乙個getmax()函式即可(這門課的作業是不允許使用stl、boost等函式庫,不過自己實現乙個簡單地queue也不難)。但是由於這道題的資料量較大,時間也很緊,使用一般的方法肯定會exceed time limit,所以如何快速的獲取最大值是這道題的難點。

當需要時才去尋找的時間複雜度為o(n),這是肯定無法滿足要求的,所以我們需要另外準備乙個堆用於維護最大值,這樣當我們需要時呼叫getmax()就只需要o(1)的時間複雜度。

那麼這樣的資料結構具體該如何實現呢?在考慮佇列之前不如先想想如何實現這樣乙個棧,因為棧的邏輯更加簡單,而且和佇列是可以互相轉換的。

由於棧的特點是先進後出,所以當乙個元素入棧時,最大值只有兩種可能,新入棧的這個元素,或是入棧之前的最大元素。我們可以在push()方法中增加乙個判斷:當新元素入棧時,將他與堆中的top()元素進行比較,如果新元素較大則將新元素加入堆中,否則將top()元素再次加入堆中,如下圖:

具體實現**如下:

templateclass steap

//出棧

void pop()

//獲得棧頂元素

t top()

//獲得最大元素

t getmax()

//判斷棧是否為空

bool empty()

};

當我們實現這樣乙個棧之後,其實問題已經迎刃而解了。因為我們可以通過2個棧來實現1個佇列,這個佇列的getmax()方法只需要返回2個棧的getmax()中較大的元素即可。**如下:

templateclass queap

//出隊

void dequeue()

s2.pop();

}//獲得隊首元素

t front()

return s2.top();

}//獲得最大元素

t getmax()

//判斷佇列是否為空

bool empty()

};

那麼有沒有方法可以直接實現佇列呢?當然有!當乙個元素入隊時,在堆中將他前面所有不大於他的元素都更新為他本身,這樣當堆前面比他大的元素都出隊後,下乙個元素自然和他一樣大。原理如圖:

這樣最壞情況入隊的時間複雜度為o(n),**如下:

templateclass queap

//出隊

void dequeue()

//獲得隊首元素

t front()

//獲得最大元素

t getmax()

//判斷佇列是否為空

bool empty()

};

資料結構 遞迴求出最大值

遞迴排序 能用遞迴解決的問題都可以使用非遞迴來完成。時間複雜度 t n a t n b o n d 1 log b,a d 複雜度為o n log b,a 2 log b,a d 複雜度為o n d logn 3 log b,a d 複雜度為o n d 在本題中,將n樣本量分成兩部分,執行兩次因此a...

資料結構 遞迴法求解棧中最大值和最小值

遞迴法求解最大值和最小值 問題描述 若乙個無序的線性表a maxsize 採用順序儲存方式,元素型別為整型數。試寫出遞迴演算法求出a中的最大元素和最小元素。要求 順序表的資料通過呼叫演算法initrandomize 隨機產生。遞迴求棧中最大值的核心 如下 int recursion max sqst...

資料結構 生成視窗最大值陣列

程式設計師 面試指南 左程雲 讀書筆記 7 第一章生成視窗最大值陣列 題目 有乙個整形陣列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...