實現一個 能在O(1)時間復雜度 完成 Push、Pop、Min操作的 棧


一,問題描述

實現一個棧(元素遵守先入后出順序),能夠通過 min 方法在 O(1)時間內獲取棧中的最小元素。同時,棧的基本操作:入棧(Push)、出棧(Pop),也是在O(1)時間內完成的。

 

二,問題分析

之所以認為這個問題有趣,是因為在實現 min 方法的過程 牽涉到了 “緩存一致性”問題。是不是聽起來很高大上?哈哈,我臆想的。

思路1:添加一個成員變量總是保存當前棧中最小的元素。該思路的實現代碼大致是這樣的:

public class MinStack {
    
    private LinkedList<Integer> stack;
    private int min;// save minimum ele of stack
    
    public int pop(){
        //check pop minimum ele?
    }
    public void push(int ele){
        //check push minimum ele?
    }
    public int getMin(){
        return min;
    }
}

 

這里就會存在一個問題:保存最小元素的 min 屬性 與 棧中的最小元素不一致。

比如:當從棧中 pop 最小元素時,那 min 屬性就要 保存 次最小元素了。那如何 找到次最小元素,然后賦值給 min 呢?

 因此,問題的關鍵就是:當只使用一個 min 屬性時,如何保證 min 屬性 總是 保存的是當前棧中最小的元素?---即: min 代表的最小元素 要與 棧中的最小元素保存一致。一種方式是當pop出最小元素之后,再遍歷棧找出次最小的元素,並將之賦值給 min 。但是,由於遍歷使得時間復雜度不再是O(1)

 

思路2:

使用一個輔助棧。此方法能夠實現在O(1)時間內獲取棧中最小的元素,但是缺點是空間復雜度為O(N)

現在有兩個棧:一個是保存元素的數據棧,另一個是輔助棧,輔助棧的棧頂總是 當前數據棧中最小的元素。當Push元素時,首先將該元素Push到數據棧,然后再將該元素與輔助棧的棧頂元素比較:如果該元素比輔助棧的棧頂元素小,則將該元素Push到輔助棧中;否則將輔助棧的棧頂元素再Push到輔助棧中。

比如,現在要Push的元素順序如下:3,4,2,5....   在數據棧 和 輔助棧中保存的元素如下:

 

三,代碼實現

代碼中使用了 java.util.LinkedList 類作為 棧的實現。

import java.util.LinkedList;

public class MinStack {
    
    private LinkedList<Integer> dataStack;
    private LinkedList<Integer> minStack;
    
    public MinStack() {
        dataStack = new LinkedList<Integer>();
        minStack = new LinkedList<Integer>();
    }
    
    //base operation
    public void push(int ele)
    {
        dataStack.push(ele);
        if(minStack.size() == 0 || ele < minStack.peek())
            minStack.push(ele);
        else
            minStack.push(minStack.peek());
    }
    
    public Integer pop(){
        if(dataStack.isEmpty())
            return null;
        
        assert dataStack.isEmpty() == false && minStack.isEmpty() == false;
        int ele = dataStack.pop();
        minStack.pop();
        return ele;
    }
    
    public Integer min(){
        if(minStack.isEmpty())
            return null;
        return minStack.peek();
    }
    
    //hapjin test
    public static void main(String[] args) {
        MinStack stack = new MinStack();
        
        int[] eles = {3,4,2,5};
        for (int i : eles) {
            stack.push(i);
        }
        System.out.println(stack.min());//2
        System.out.println(stack.pop());//5
        System.out.println(stack.pop());//2
        System.out.println(stack.min());//3
        stack.push(1);
        System.out.println(stack.min());
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM