LeetCode算法題-Min Stack(Java實現)
這是悅樂書的第177次更新,第179篇原創
01 看題和準備
今天介紹的是LeetCode算法題中Easy級別的第36題(順位題號是155)。設計一個支持push,pop,top和在恒定時間內檢索最小元素的堆棧。
push(x) - 將元素x推入堆棧。
pop() - 刪除堆棧頂部的元素。
top() - 獲取頂部元素。
getMin() - 檢索堆棧中的最小元素。
例如:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); - >返回-3。
minStack.pop();
minStack.top(); - >返回0。
minStack.getMin(); - >返回-2。
本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。
02 第一種解法
利用整型數組和ArrayList作為棧。
入棧的時候,創建一個容量為2的數組,數組第一個元素是要入棧的元素,第二個元素是最小值,將數組添加到list中。
出棧的時候,獲取list的最後一個元素,並將其移除,此時的最小值是list最後一位元素(數組)的第二個值。
獲取棧頂,即是list中最後一位元素(數組)的第一個值。
最小值直接返回最小值即可。
class MinStack { private List<int[]> stack ; private int min ; public MinStack() { stack = new ArrayList<int[]>(); } public void push(int x) { int[] arr = new int[2]; arr[0] = x; arr[1] = stack.isEmpty() ? x : Math.min(x, min); min = arr[1]; stack.add(arr); } public void pop() { if (!stack.isEmpty()) { stack.remove(stack.size()-1); min = stack.isEmpty() ? 0 : stack.get(stack.size()-1)[1]; } } public int top() { return stack.get(stack.size()-1)[0]; } public int getMin() { return min; } }
03 第二種解法
此解法使用了棧本身和優先隊列兩種結構,優先隊列是為了解決最小值的問題。
入棧、出棧、棧頂這些操作都可以用棧本身的方法,而最小值則是優先隊列的頭部元素,因為優先隊列自帶排序算法,在初始化時如果不指定排序方式,則默認以自然方式排序。所以在入棧時,一並也將元素放入優先隊列中,而最小值就是隊列的頭部元素,而其他元素的順序是不是按升序依次排列的,這個還真不一定,但是如果你通過實現Comparable接口,重寫其compareTo方法,可以按照自己定義的方式來排序。
class MinStack2 {
PriorityQueue<Integer> pQueue = new PriorityQueue<Integer>();
Stack<Integer> stack = new Stack<Integer>();
public MinStack2() {}
public void push(int x) {
pQueue.add(x);
stack.push(x);
}
public void pop() {
int trmp = stack.pop();
pQueue.remove(trmp);
}
public int top() {
return stack.peek();
}
public int getMin() {
return pQueue.peek();
}
}
04 第三種解法
使用兩個棧,一個作為正常的棧進行入棧、出棧、獲取棧頂操作,另外一個棧則存儲最小值,每次在第一個棧進行入棧和出棧操作時,都要進行判斷,對第二個棧中的最小值進行相應的操作。
class MinStack3 {
private Stack<Integer> s1 = new Stack<>();
private Stack<Integer> s2 = new Stack<>();
public MinStack3() {}
public void push(int x) {
s1.push(x);
if (s2.isEmpty() || s2.peek() >= x) {
s2.push(x);
}
}
public void pop() {
int x = s1.pop();
if (s2.peek() == x) s2.pop();
}
public int top() {
return s1.peek();
}
public int getMin() {
return s2.peek();
}
}
05 第四種解法
較之第三種解法,此解法只使用了一個棧來完成入棧、出棧、獲取棧頂和最小值的全部操作。
入棧時,如果新入棧的元素比最小值小,那麽要將舊的最小值入棧,並且新的最小值是此時新入棧的元素,最後再將新元素入棧。
出棧時,如果要移除的元素正好是當前最小值,那麽就需要再出棧一次,並且最小值等於第二次出棧要移除的值,因為入棧時是會將舊的最小值添加進去的,所以出棧時要做此判斷。
class MinStack4 {
int min = Integer.MAX_VALUE;
Stack<Integer> stack = new Stack<Integer>();
public void push(int x) {
if(x <= min){
stack.push(min);
min = x;
}
stack.push(x);
}
public void pop() {
if(stack.pop() == min) {
min=stack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return min;
}
}
06 小結
算法專題目前已連續日更超過一個月,算法題文章35+篇,公眾號對話框回復【數據結構與算法】、【算法】、【數據結構】中的任一關鍵詞,獲取系列文章合集。
以上就是全部內容,如果大家有什麽好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支持!
LeetCode算法題-Min Stack(Java實現)