題目:定義棧的數據結構,請在該類型中實現一個可以獲得棧的最小元素的min函數。在該棧中,調用min,push及pop的時間複雜度都是O(1).java
看到這個問題,咱們的第一反應多是每次壓入一個新元素進棧時,將棧裏的全部元素排序,讓最小的元素位於棧頂,這樣就能在O(1)時間獲得最小元素了。但這種思路不能保證最後壓入的元素可以最早出棧,所以這個數據結構已經不是棧了。node
咱們接着想到在棧裏添加一個成員變量存放最小的元素。每次壓入一個新元素進棧的時候,若是該元素比當前最小的元素還要小,則更新最小元素。面試官聽到這種思路以後就會問:若是當前最小的元素被彈出棧了,如何獲得下一個最小的元素呢?面試
分析到這裏咱們發現僅僅添加一個成員變量存放最小元素是不夠的,也就是說當最小元素彈出棧的時候,咱們但願可以獲得次小元素。所以在壓入這個最小元素以前,咱們要把次小元素保存起來。所以,在壓入這個最小元素以前,咱們要把次小元素保存起來。數據結構
是否是能夠把每次的最小元素都保存起來,放在另一個輔助棧裏呢?咱們不妨舉幾個例子來分析一下把元素壓入或者彈出棧的過程。函數
題關鍵在於用輔助棧儲存什麼值。要保證輔助棧的top是最小值,pop以後的頂部仍然是最小值。也就是說輔助棧從上到下存儲的應該是最小值->次小值->次次小值……排序
這裏容易進入一個誤區就是:難道輔助棧就是對數據棧的排序?若是真是這樣,push的時候由於要排序不能知足O(1);數據棧pop的時候,輔助棧要先查找數據棧pop出去的值而後再pop,也不知足O(1)。class
當兩個棧爲空時,push進去的第一個值即爲最小值;import
push第二個元素時,若push的值<輔助棧頂元素(此處即第一個值),則將此值壓進輔助棧;若push的值大於等於輔助棧頂元素,則將輔助棧頂元素再次push進去。變量
pop的時候,數據棧輔助棧均彈出頂元素。im
實現代碼以下:
package cglib;
import java.util.Stack;
public class DeleteNode {
Stack<Integer> stack1 = new Stack<Integer>(); // 數據棧
Stack<Integer> stack2 = new Stack<Integer>(); // 輔助棧 用於返回min值
public void push(int node) {
stack1.push(node);
if (stack2.empty()) {
stack2.push(node);
} else {
if (node < stack2.peek().intValue())//若是進入的數小於輔助棧的棧頂元素
stack2.push(node);//則放進去進入的數
else stack2.push(stack2.peek());//不然放進輔助棧的棧頂元素
}
}
@SuppressWarnings("null")
public int pop() {
if(stack1.empty()||stack2.empty()){
return (Integer) null;
}
stack2.pop();
return stack1.pop();
}
public int top() {
if (!stack1.empty())
return stack1.peek().intValue();
else return 0;
}
public int min() {
if (!stack2.empty())
return stack2.peek().intValue();
else return 0;
}
public static void main(String[] args) {
DeleteNode ms = new DeleteNode();
ms.push(4);
ms.push(3);
ms.push(1);
ms.push(5);
ms.push(2);//4,3,1,5,2
//System.out.println("pop:" +ms.pop() );
System.out.println("min:" + ms.min() + " pop:" +ms.pop() );
System.out.println("min:" + ms.min() + " pop:" +ms.pop() );
System.out.println("min:" + ms.min() + " pop:" +ms.pop() );
System.out.println("min:" + ms.min() + " pop:" +ms.pop() );
}
}
輸出:
min:1 pop:2 min:1 pop:5 min:1 pop:1 min:3 pop:3