1、題目分析
實現一個棧,該棧帶有出棧(pop)、入棧(push)、取最小元素(getMin)3 個方法,保證這3個方法的時間複雜度都是O(1)。
方法一【錯誤】
方法流程:
- 創建一個整型變量min,用來存儲棧中的最小元素;當第1個元素進棧時, 把進棧元素賦值給min,即把棧中唯一的元素當做最小值
- 之後每當一個新元素進棧,就讓新元素和min比較大小。如果新元素小於min,則min等於新進棧的元素;如果新元素大於或等於min,則不做改變;
- 當調用getMin方法時,直接返回min的值即可
錯誤分析:【只考慮了進棧場景,卻沒有考慮出棧場景】
- 棧中最小的元素是3,min變量記錄的值也是3
- 棧頂元素出棧
雖然此時的最小元素是4,但是程序並不知道
方法二【正確】
解法步驟:
- 設原有的棧叫作棧A,此時創建一個額外的“備胎”棧B,用於輔助棧A
- 當第1個元素進入棧A時,讓新元素也進入棧B。這個唯一的元素是棧A的當 前最小值
- 每當新元素進入棧A時,比較新元素和棧A當前最小值的大小,如果小於棧A當前最小值,則讓新元素進入棧B,此時棧B的棧頂元素就是棧A當前最小值
- 每當棧A有元素出棧時,如果出棧元素是棧A當前最小值,則讓棧B的棧頂元素也出棧;此時棧B餘下的棧頂元素所指向的是棧A當中原本第2小的元素,代替剛纔的出棧元素成爲棧A的當前最小值(備胎轉正)
當調用getMin方法時,返回棧B的棧頂所存儲的值,這也是棧A的最小值。
這個解法中進棧、出棧、取最小值的時間複雜度都是O(1),最壞情況空間複雜度是O(n)
2、代碼實現
Code:
import java.util.Stack;
/**
* @ClassName minStack
* @Description //最小棧的實現
* @Date: 2020/4/8
* @Version 1.0
*/
public class minStack {
private Stack<Integer> mainStack = new Stack<Integer>();
private Stack<Integer> minStack = new Stack<Integer>();
/**
* 入棧操作
* @param element 入棧的元素
*/
public void push(int element){
mainStack.push(element);
//如果輔助棧爲空,或者新元素小於或等於輔助棧棧頂,則將新元素壓入輔助棧
if(minStack.empty() || element <= minStack.peek()){
minStack.push(element);
}
}
/**
* 出棧操作
*/
public Integer pop(){
//如果出棧元素和輔助棧棧頂元素值相等,輔助棧出棧
if(mainStack.peek().equals(minStack.peek())){
minStack.pop();
}
return mainStack.pop();
}
/**
* 獲取棧的最小元素
*/
public int getMin() throws Exception{
if(mainStack.empty()){
throw new Exception("stack is empty");
}
return minStack.peek();
}
public static void main (String[] args) throws Exception{
minStack stack = new minStack();
stack.push(4);
stack.push(9);
stack.push(7);
stack.push(3);
stack.push(8);
stack.push(5);
System.out.println("當前棧中的最小元素爲:"+ stack.getMin());
stack.pop();
stack.pop();
stack.pop();
System.out.println("當前棧中的最小元素爲:"+ stack.getMin());
}
}
編譯輸出:
———————————————————————————————————————
內容來源:《漫畫算法》
關注公衆號,回覆 【算法】,獲取高清算法書!