1. 程式人生 > >菜鳥系列之C/C++經典試題(三)

菜鳥系列之C/C++經典試題(三)

最小 新元素 一道 數據 步驟 時間 name val type

設計包括min函數的棧

題目:定義棧的數據結構,要求加入一個min函數,可以得到棧的最小元素。要求函數min、push以及pop的時間復雜度都是O(1)。

分析:這是2006年google的一道面試題。

我看到這道題目時,第一反應就是每次push一個新元素時,將棧裏全部逆序元素排序。

這樣棧頂元素將是最小元素。但因為不能保證最後push進棧的元素最先出棧,這樣的思路設計的數據結構已經不是一個棧了。

在棧裏加入一個成員變量存放最小元素(或最小元素的位置)。每次push一個新元素進棧的時候,假設該元素比當前的最小元素還要小,則更新最小元素。

乍一看這樣思路挺好的。但細致一想,該思路存在一個重要的問題:假設當前最小元素被pop出去,怎樣才幹得到下一個最小元素?

因此只只加入一個成員變量存放最小元素(或最小元素的位置)是不夠的。我們須要一個輔助棧。每次push一個新元素的時候,同一時候將最小元素(或最小元素的位置。考慮到棧元素的類型可能是復雜的數據結構,用最小元素的位置將能降低空間消耗)push到輔助棧中;每次pop一個元素出棧的時候。同一時候pop輔助棧。

參考代碼:

#include <deque>
#include <assert.h>

template <typename T> class CStackWithMin
{
public:
    CStackWithMin(void) {}
    virtual ~CStackWithMin(void) {}

    T& top(void);
    const T& top(void) const;

    void push(const T& value);
    void pop(void);

    const T& min(void) const;

private:
    T > m_data;               // the elements of stack
    size_t > m_minIndex;      // the indices of minimum elements
};

// get the last element of mutable stack
template <typename T> T& CStackWithMin<T>::top()
{
    return m_data.back();
}

// get the last element of non-mutable stack
template <typename T> const T& CStackWithMin<T>::top() const
{
    return m_data.back();
}

// insert an elment at the end of stack
template <typename T> void CStackWithMin<T>::push(const T& value)
{
    // append the data into the end of m_data
    m_data.push_back(value);

    // set the index of minimum elment in m_data at the end of m_minIndex
    if (m_minIndex.size() == 0)
        m_minIndex.push_back(0);
    else
    {
        if (value < m_data[m_minIndex.back()])
            m_minIndex.push_back(m_data.size() - 1);
        else
            m_minIndex.push_back(m_minIndex.back());
    }
}

// erease the element at the end of stack
template <typename T> void CStackWithMin<T>::pop()
{
    // pop m_data
    m_data.pop_back();

    // pop m_minIndex
    m_minIndex.pop_back();
}

// get the minimum element of stack
template <typename T> const T& CStackWithMin<T>::min() const
{
    assert(m_data.size() > 0);
    assert(m_minIndex.size() > 0);

    return m_data[m_minIndex.back()];
}

舉個樣例演示上述代碼的執行過程:

步驟 數據棧 輔助棧 最小值
1.push 3 3 0 3
2.push 4 3,4 0,0 3
3.push 2 3,4,2 0,0,2 2
4.push 1 3,4,2,1 0,0,2,3 1
5.pop 3,4,2 0,0,2 2
6.pop 3,4 0,0 3
7.push 0 3,4,0 0,0,2 0

討論:假設思路正確。編寫上述代碼不是一件非常難的事情。但假設能註意一些細節無疑能在面試中加分。

比方我在上面的代碼中做了例如以下的工作:

· 用模板類實現。假設別人的元素類型僅僅是int類型。模板將能給面試官帶來好印象。

· 兩個版本號的top函數。在非常多類中。都須要提供const和非const版本號的成員訪問函數;

· min函數中assert。把代碼寫的盡量安全是每一個軟件公司對程序猿的要求;

· 加入一些凝視。凝視既能提高代碼的可讀性,又能添加代碼量,何樂而不為?

總之,在面試時假設時間同意。盡量把代碼寫的美麗一些。說不定代碼中的幾個小亮點就能讓自己輕松拿到心儀的Offer。

原文鏈接:http://zhedahht.blog.163.com/blog/static/25411174200712895228171/

謝謝分享。 轉載表明出處。

菜鳥系列之C/C++經典試題(三)