天天看點

實作棧,擷取棧中最小值空間換時間

實作棧,擷取棧中最小值

  • 空間換時間
    • 基本思想
    • 代碼
      • 複雜度分析
    • 時間換空間
    • 基本思想
    • 代碼
      • 複雜度分析

兩種方式實作,第一種用空間換時間,第二種用時間換空間

空間換時間

基本思想

  • 用兩個棧來實作,一個棧維護入棧資料(資料棧),一個棧維護最小值(最小棧)
  • 元素入棧時,比較入棧元素與最小棧棧頂
    • 如果最小棧棧頂元素更小,那麼再次将該最小棧棧頂元素壓入最小棧
    • 如果入棧元素更小,那麼将入棧的元素同步壓入最小棧
  • 元素出棧時,資料棧與最小棧同步出棧即可,最小棧彈出元素即為目前棧中最小值

代碼

import java.util.Stack;

/**
 * 實作棧,并且可以擷取棧中的最小值
 *
 * 解決:兩個棧 -> 棧1維護所有資料,棧2維護最小值
 */
public class MinStack {

    public static class MyStack{
        //初始化定義兩個棧
        public Stack<Integer> dataStack;
        public Stack<Integer> minStack;

        public MyStack(){
            dataStack = new Stack<>();
            minStack = new Stack<>();
        }

        //入棧
        public void push(int value){
            //判斷最小棧的處理
            //若最小棧為空或最小棧棧頂值大于傳入值,則放入
            if (minStack.isEmpty() || minStack.peek() > value){
                minStack.push(value);
            } else {
                //否則,再次在最小棧放入最小棧棧頂元素
                minStack.push(minStack.peek());
            }
            //資料棧放入值
            dataStack.push(value);
        }

        //出棧
        public int pop(){
            //判空
            if (dataStack.isEmpty()){
                System.out.println("棧空");
                return -1;
            }

            //彈出最小棧棧頂,傳回資料棧棧頂
            minStack.pop();
            System.out.println(dataStack.peek());
            return dataStack.pop();
        }

        public int getMin(){
            return minStack.peek();
        }
    }

    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        myStack.push(5);
        System.out.println(myStack.getMin()); // 5 5
        myStack.push(2);
        System.out.println(myStack.getMin()); // 2 2
        myStack.push(3);
        System.out.println(myStack.getMin()); // 3 2
        myStack.push(1);
        System.out.println(myStack.getMin()); // 1 1
        myStack.pop();
        System.out.println(myStack.getMin()); // 3 2
    }
}
           

複雜度分析

所謂空間換時間,
就是元素每次進棧時,最小棧同步會壓入,占用了和資料棧同等大小的空間
但擷取棧中的最小值時,隻需要擷取最小棧棧頂元素即可,節省了時間
           

時間換空間

基本思想

  • 同樣定義資料棧和最小棧
  • 元素入棧時,比較入棧元素與最小棧棧頂
    • 如果入棧元素>最小棧棧頂元素,則最小棧不壓入
    • 如果入棧元素<=最小棧棧頂元素,則最小棧同步壓入
  • 元素出棧時
    • 隻有資料棧棧頂元素與最小棧棧頂元素相等時,才會同步彈出
    • 這樣才可以保證最小棧棧頂元素始終為棧的最小值

代碼

import java.util.Stack;

/**
 * 實作棧,并且可以擷取棧中的最小值
 *
 * 解決:兩個棧 -> 棧1維護所有資料,棧2維護最小值
 *      入棧時:棧2隻有在其棧頂元素≤目前值時才入棧
 *      出棧時:棧2隻有棧頂元素 = 資料棧棧頂元素時才出棧
 */
public class MinStack2 {

    public static class MyStack{
        //初始化定義兩個棧
        public Stack<Integer> dataStack;
        public Stack<Integer> minStack;

        public MyStack(){
            dataStack = new Stack<>();
            minStack = new Stack<>();
        }

        //入棧
        public void push(int value){
            //判斷最小棧的處理
            //若最小棧為空或傳入值≤最小棧棧頂值,則放入
            if (minStack.isEmpty() || value <= minStack.peek()){
                minStack.push(value);
            }
            //資料棧放入值
            dataStack.push(value);
        }

        //出棧
        public int pop(){
            //判空
            if (dataStack.isEmpty()){
                System.out.println("棧空");
                return -1;
            }

            //若資料棧棧頂=最小棧棧頂,彈出最小棧棧頂,傳回資料棧棧頂
            if (dataStack.peek() == minStack.peek()){
                minStack.pop();
            }
            System.out.println(dataStack.peek());
            return dataStack.pop();
        }

        public int getMin(){
            return minStack.peek();
        }
    }

    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        myStack.push(5);
        System.out.println(myStack.getMin()); // 5 5
        myStack.push(2);
        System.out.println(myStack.getMin()); // 2 2
        myStack.push(3);
        System.out.println(myStack.getMin()); // 3 2
        myStack.push(1);
        System.out.println(myStack.getMin()); // 1 1
        myStack.pop();
        System.out.println(myStack.getMin()); // 3 2
    }
}
           

複雜度分析

所謂時間換空間,
就是元素每次進棧時,最小棧不會同步會壓入,隻有<=最小棧棧頂元素時才會壓入,最小棧占用空間會小
但擷取棧中的最小值時,需要判斷資料棧棧頂元素與最小棧棧頂元素是否相等,相等時才會彈出,因為增加了邏輯判斷,是以會比方法一占用更多的時間
           

繼續閱讀