劍指Offer——包含min函數的棧

題目描述

定義棧的數據結構,請在該類型中實現一個能夠得到棧最小元素的min函數。調用min、push及pop的時間複雜度都是O(1)。

方法一

考慮使用兩個棧,一個數據棧(就是普通的棧),實現棧的push、pop等操作;另一個輔助棧用來存放每次棧操作時(包括入棧和出棧)棧中最小元素。

輔助棧的操作:棧頂元素爲當前棧中的最小元素

  • 要獲取當前棧中最小元素,只需要返回棧頂元素即可;
  • 每次執行push操作,檢查push的元素與棧頂元素的大小關係。將較小的元素push到輔助棧中。
  • 當執行pop操作的時候,將輔助棧中的棧頂元素pop出去。

實例:

代碼

class Solution {
public:
    stack<int> data;
    stack<int> minNum;
     
    void push(int value) {
        data.push(value);
        if( minNum.empty() )
            minNum.push(value);
        else
            minNum.push( minNum.top()<value?minNum.top():value );
    }
    void pop() {
//        assert( !data.empty() && !minNum.empty() );
        data.pop();
        minNum.pop();
    }
    int top() {
        return data.top();
    }
    int min() {
        return minNum.top();
    }
};
簡單優化:對於輔助棧的操作,每次執行push操作時,檢查push的元素是否小於或等於輔助棧棧頂元素。如果是,則也push該元素到輔助棧中。當執行pop操作的時候,檢查pop的元素是否與當前最小值相等。如果相同,則需要將該元素從輔助棧中pop出去。其餘情況對於輔助棧可以不做修改。

方法二

解法利用存儲差值而不需要輔助棧,方法比較巧妙。該方法需要額外使用佔用一個空間存儲當前棧中的最小值,將最小值一直儲存在棧頂。
  • 當需要push進一個新值value時,先將最小值pop出來,在棧中壓入value與當前棧中最小元素的差值,然後比較value與當前棧中最小元素大小,將它們中間的較小值壓入棧。
  • 執行min()函數時,直接返回棧頂元素即可。
  • 執行top()函數時,返回棧頂兩個元素的和即可。
  • 執行pop()函數時,先pop出棧頂的兩個值,這兩個值分別是當前棧中最小值min和最後壓入的元素與棧中最小值的差值diff,因爲pop()函數需要把最後存入的值刪除,所以只需要考慮pop後的最小值min是多少,並將其壓入棧中。如果diff<0,則表示最後壓入棧的元素是最小的元素,因此只需將min-diff壓入棧中,min-diff就是當前元素彈出後,棧中剩下元素的最小值。而如果diff>=0且棧不爲空,則表示當前值不是最小值,所以需要在棧中壓入最小值min。
一個實例如下:
clear(): [ ] 
push(3): [3 3] 
push(4): [3 1 3] 
push(2): [3 1 -1 2] 
push(5): [3 1 -1 3 2] 
push(1): [3 1 -1 3 -1 1] 
push(1): [3 1 -1 3 -1 0 1] 
push(6): [3 1 -1 3 -1 0 5 1] 
push(7): [3 1 -1 3 -1 0 5 6 1]

min() --> 1; pop() --> 7: [3 1 -1 3 -1 0 5 1] 
min() --> 1; pop() --> 6: [3 1 -1 3 -1 0 1] 
min() --> 1; pop() --> 1: [3 1 -1 3 -1 1] 
min() --> 1; pop() --> 1: [3 1 -1 3 2] 
min() --> 2; pop() --> 5: [3 1 -1 2] 
min() --> 2; pop() --> 2: [3 1 3] 
min() --> 3; pop() --> 4: [3 3] 
min() --> 4; pop() --> 3: [ ]

代碼

class Solution {
public:
    stack<int> data;
    void push(int value) {
        if( data.empty() )
        {
            data.push(value);
            data.push(value);
            return;
        }
        int min = data.top();
        data.pop();
        if( min <= value )
        {
            data.push(value-min);
            data.push(min);
            return;
        }
        else
        {
            data.push(value-min);
            data.push(value);
            return;
        }
        return;
    }
    void pop() {
        int min = data.top();
        data.pop();
        if( data.top() >= 0 )
        {
            data.pop();
            data.push(min);
            return;
        }
        else
        {
            int temp = data.top();
            data.pop();
            data.push(min-temp);
        }
        return;
    }
    int top() {
        int min = data.top();
        data.pop();
        int res = data.top()+min;
        data.push(min);
        return res;
    }
    int min() {
        return data.top();
    }
};

參考文獻:

https://www.cnblogs.com/javawebsoa/archive/2013/05/21/3091727.html

https://blog.csdn.net/sgbfblog/article/details/7752878
發佈了52 篇原創文章 · 獲贊 54 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章