本文參考自《劍指offer》一書,代碼采用Java語言。
題目
請定義一個隊列並實現函數max得到隊列里的最大值,要求函數max、push_back和pop_front的時間復雜度都是O(1)。
思路
與滑動窗口的最大值一題相似,利用一個雙端隊列來存儲當前隊列里的最大值以及之后可能的最大值。
在定義題目要求功能的隊列時,除了定義一個隊列data存儲數值,還需額外用一個隊列maxmium存儲可能的最大值;此外,還要定義一個數據結構,用於存放數據以及當前的index值,用於刪除操作時確定是否刪除maxmium中最大值。
具體實現見代碼,代碼進行了一些測試,應該沒有什么問題。
測試算例
尾部插入不同大小數字,刪除頭部數字。插入刪除同時獲取最大值。
Java代碼
import java.util.ArrayDeque;
//題目:請定義一個隊列並實現函數max得到隊列里的最大值,要求函數max、
//push_back和pop_front的時間復雜度都是O(1)。
public class QueueWithMax {
private ArrayDeque<InternalData> data = new ArrayDeque<InternalData>();
private ArrayDeque<InternalData> maximum = new ArrayDeque<InternalData>();
private class InternalData{
int number;
int index;
public InternalData(int number,int index) {
this.number=number;
this.index=index;
}
}
private int curIndex;
public void push_back(int number) {
InternalData curData = new InternalData(number,curIndex);
data.addLast(curData);
while(!maximum.isEmpty() && maximum.getLast().number<number)
maximum.removeLast();
maximum.addLast(curData);
curIndex++; //別漏了這句
}
public void pop_front() {
if(data.isEmpty()) {
System.out.println("隊列為空,無法刪除!");
return;
}
InternalData curData = data.removeFirst();
if(curData.index==maximum.getFirst().index)
maximum.removeFirst();
}
public int max() {
if(maximum==null){
System.out.println("隊列為空,無法刪除!");
return 0;
}
return maximum.getFirst().number;
}
public static void main(String[] args) {
QueueWithMax testQueue = new QueueWithMax();
// {2}
testQueue.push_back(2);
System.out.println(testQueue.max()==2);
// {2, 3}
testQueue.push_back(3);
System.out.println(testQueue.max()==3);
// {2, 3, 4}
testQueue.push_back(4);
System.out.println(testQueue.max()==4);
// {2, 3, 4, 2}
testQueue.push_back(2);
System.out.println(testQueue.max()==4);
// {3, 4, 2}
testQueue.pop_front();
System.out.println(testQueue.max()==4);
// {4, 2}
testQueue.pop_front();
System.out.println(testQueue.max()==4);
// {2}
testQueue.pop_front();
System.out.println(testQueue.max()==2);
// {2, 6}
testQueue.push_back(6);
System.out.println(testQueue.max()==6);
// {2, 6, 2}
testQueue.push_back(2);
System.out.println(testQueue.max()==6);
// {2, 6, 2, 5}
testQueue.push_back(5);
System.out.println(testQueue.max()==6);
// {6, 2, 5}
testQueue.pop_front();
System.out.println(testQueue.max()==6);
// {2, 5}
testQueue.pop_front();
System.out.println(testQueue.max()==5);
// {5}
testQueue.pop_front();
System.out.println(testQueue.max()==5);
// {5, 1}
testQueue.push_back(1);
System.out.println(testQueue.max()==5);
}
}
true true true true true true true true true true true true true true
收獲
1.在定義private ArrayDeque<InternalData> data時,別忘記了new ArrayDeque<InternalData>();否則在插入數據時,會拋出NPE異常。
2.進行刪除操作時,注意是否隊列是否為空。
