一篇學會包含 Min 函數的棧
本文轉載自微信公眾號「程序員千羽」,作者程序員千羽 。轉載本文請聯(lián)系程序員千羽公眾號。
Leetcode : https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof
“GitHub : https://gitee.com/nateshao/leetcode/blob/main/algo-notes/src/main/java/com/nateshao/sword_offer/topic_23_MinStack/MinStack.java
包含min函數的棧
“題目描述 :定義棧的數據結構,請在該類型中實現(xiàn)一個能夠得到棧的最小元素的 min 函數在該棧中,調用 min、push 及 pop 的時間復雜度都是 O(1)。示例:
- MinStack minStack = new MinStack();
- minStack.push(-2);
- minStack.push(0);
- minStack.push(-3);
- minStack.min(); --> 返回 -3.
- minStack.pop();
- minStack.top(); --> 返回 0.
- minStack.min(); --> 返回 -2.
- 提示:
各函數的調用總次數不超過 20000 次
解題思路: 定義兩個棧,一個存放入的值。另一個存最小值。
“普通棧的 push() 和 pop() 函數的復雜度為 O(1) ;而獲取棧最小值 min() 函數需要遍歷整個棧,復雜度為 O(N) 。
- 本題難點:將min() 函數復雜度降為0(1),可通過建立輔助棧實現(xiàn);
- 數據棧A:棧A用于存儲所有元素,保證入棧push() 函數、出棧pop() 函數、獲取棧頂top()函數的正常邏輯。
- 輔助棧B:棧B中存儲棧A中所有非嚴格降序的元素,則棧A中的最小元素始終對應棧B的棧頂元素,即min() 函數只需返回棧B的棧頂元素即可。
因此,只需設法維護好棧B的元素,使其保持非嚴格降序,即可實現(xiàn)min() 函數的0(1)復雜度。
函數設計:
- push(x) 函數: 重點為保持棧 B 的元素是 非嚴格降序 的。
- 將 x 壓入棧 A(即 A.add(x) );
- 若 ① 棧 B 為空 或 ② x 小于等于 棧 B 的棧頂元素,則將 x 壓入棧 B (即 B.add(x) )。
- pop() 函數: 重點為保持棧 A, B 的 元素一致性 。
- 執(zhí)行棧 A 出棧(即 A.pop() ),將出棧元素記為 y ;
- 若 y 等于棧 B 的棧頂元素,則執(zhí)行棧 B 出棧(即 B.pop() )。
- top() 函數: 直接返回棧 A 的棧頂元素即可,即返回 A.peek() 。
- min() 函數: 直接返回棧 B 的棧頂元素即可,即返回 B.peek() 。
復雜度分析:
- 時間復雜度 O(1) : push(), pop(), top(), min() 四個函數的時間復雜度均為常數級別。
- 空間復雜度 O(N) : 當共有 N個待入棧元素時,輔助棧 B最差情況下存儲 N 個元素,使用 O(N)額外空間。
“Java 代碼中,由于 Stack 中存儲的是 int 的包裝類 Integer ,因此需要使用 equals() 代替 == 來比較值是否相等。此題如果用==將會無法通過 Integer的equals重寫過,比較的是內部value的值, ==如果在[-128,127]會被cache緩存,超過這個范圍則比較的是對象是否相同
- package com.nateshao.sword_offer.topic_23_MinStack;
- import java.util.Stack;
- /**
- * @date Created by 邵桐杰 on 2021/11/28 21:38
- * @微信公眾號 程序員千羽
- * @個人網站 www.nateshao.cn
- * @博客 https://nateshao.gitee.io
- * @GitHub https://github.com/nateshao
- * @Gitee https://gitee.com/nateshao
- * Description: 包含min函數的棧
- * 思路:定義兩個棧,一個存放入的值。另一個存最小值。
- */
- public class MinStack {
- private Stack<Integer> stack1; // 數據棧
- private Stack<Integer> stack2; // 輔助棧,記錄每次有元素進棧后或者出棧后,元素的最小值
- /**
- * initialize your data structure here.
- */
- public MinStack() {
- // 初始化輔助棧和數據棧
- stack1 = new Stack<>();
- stack2 = new Stack<>();
- }
- public void push(int x) {
- // 數據棧,進棧
- stack1.push(x);
- // 如果記錄當前數據棧中最小值的輔助棧為空,或者最小值小于 x,則將 x 設置為最小值,即進輔助棧
- if (stack2.isEmpty() || stack2.peek() >= x) stack2.push(x);
- }
- public void pop() {
- if (stack1.pop().equals(stack2.peek())) stack2.pop();
- }
- public int top() {
- return stack1.peek();
- }
- public int min() {
- return stack2.peek();
- }
- /**
- * Your MinStack object will be instantiated and called as such:
- * MinStack obj = new MinStack();
- * obj.push(x);
- * obj.pop();
- * int param_3 = obj.top();
- * int param_4 = obj.min();
- */
- /**
- * 精選解答
- */
- class MinStack1 {
- Stack<Integer> A, B;
- public MinStack1() {
- A = new Stack<>();
- B = new Stack<>();
- }
- public void push(int x) {
- A.add(x);
- if (B.empty() || B.peek() >= x)
- B.add(x);
- }
- public void pop() {
- if (A.pop().equals(B.peek()))
- B.pop();
- }
- public int top() {
- return A.peek();
- }
- public int min() {
- return B.peek();
- }
- }
- }
參考鏈接:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/solution