栈面试题总结

1.求栈上的最小值

具体要求:在O(1)的时间复杂度内求出栈上的最小值,并且不受出栈入栈的影响。
思路:借助一个辅助栈,原栈在有数据入栈的时候,辅助栈也有数据入栈。辅助栈入栈的数据为当前的最小值。
实现:

template<typename T>
class StackMin
{
public:
    void Push(const T&data);
    void Pop();
    T Min();
private:
    stack<T>st1;
    stack<T>st2;
};

template<typename T>
void StackMin<T>::Push(const T&data)
{
    st1.push(data);
    if (st2.size() == 0 || st2.top() > data)
        st2.push(data);
    else
        st2.push(st2.top());
}

template<typename T>
void StackMin<T>::Pop()
{
    if (st1.size() == 0)
        return;
    st1.pop();
    st2.pop();
}

template<typename T>
T StackMin<T>::Min()
{
    return st2.top();
}

2.利用两个栈实现队列

具体要求:实现队列的push,pop,front,back操作
思路:栈上的数据为先进后出,队列上的数据为先进先出。可以用栈1专门用来放push的数据,如果要pop的时候,就把栈1的数据存入到栈2中去,对栈2进行pop。
实现:

template<typename T>
class QueueOfTwoStack
{
public:
    void Push(const T&data);
    void Pop();
    T&Front()可以合并
    {
        if (st2.empty())
        {
            while (!st1.empty())
            {
                st2.push(st1.top());
                st1.pop();
            }
        }
        return st2.top();
    }
    T&Back()
    {
        if (st1.empty())
        {
            while (!st2.empty())
            {
                st1.push(st2.top());
                st2.pop();
            }
        }
        return st1.top();
    }
private:
    stack<T>st1;
    stack<T>st2;
};

template<typename T>
void QueueOfTwoStack<T>::Push(const T&data)
{
    st1.push(data);
}

template<typename T>
void QueueOfTwoStack<T>::Pop()
{
    if (st2.size() == 0)
    {
        int count = st1.size();
        for (size_t i = 0; i < count; i++)
        {
            st2.push(st1.top());
            st1.pop();
        }
        st2.pop();
    }
    else
        st2.pop();
}

3.利用两个队列实现栈

具体要求:实现栈的Push,pop,top操作
思路:队列的数据是满足先进先出,栈上的数据满足先进后出。可以用一个队列来接收数据,当要出数据的时候,把前面的数据都放到另一个队列上去,留下最后一个。然后交换两个队列,进行下一波操作。
实现:

template<typename T>
class StackWithTwoQueue
{
public:
    void Push(const T&data);
    void Pop();
    T&Top()
    {
        assert(!qu1.empty());
        return qu1.back();
    }
private:
    queue<T>qu1;
    queue<T>qu2;
};


template<typename T>
void StackWithTwoQueue<T>::Push(const T&data)
{
    qu1.push(data);
}

template<typename T>
void StackWithTwoQueue<T>::Pop()
{
    if (0 == qu1.size())
        return;
    int count = qu1.size();
    for (int i = 0; i < count - 1; i++)
    {
        qu2.push(qu1.front());
        qu1.pop();
    }
    qu1.pop();
    swap(qu1, qu2);//交换
}

4.数组判断是否为出栈顺序

具体要求:如果是对的顺序就返回true,否则返回false
思路:借助一个栈来实现,将Push的值挨个入栈,同时进行判断栈顶的值是否与pop的第一个值相等,如果相同就出栈。最后如果栈为空,并且pop的也走到了最后,就说明是出栈顺序。
实现:

bool IsPopOrder(const int*pPush, const int*pPop, int length)
{
    bool ret = false;
    if (NULL == pPush || NULL == pPop || length <= 0)
        return ret;
    const int*pNextPush = pPush;
    const int*pNextPop = pPop;
    stack<int>s;
    while (pNextPop - pPop < length)
    {
        while (s.size() == 0 || *pNextPop != s.top())
        {
            if (pNextPush - pPush == length)
                break;
            s.push(*pNextPush);
            pNextPush++;
        }
        if (s.top() != *pNextPop)
            break;
        s.pop();
        pNextPop++;
    }
    if (s.empty() && pNextPop - pPop == length)
        ret = true;
    return ret;
}

5.背包问题
具体要求:背包的承重固定,从一系列物品中挑出刚好能放满背包的所有物品。
思路:借助一个栈来实现,栈中放的是物品数组的下标。依次往栈中放元素,如果超过了承重,就将其pop,放入一个元素来比较。
实现:

void backpack(int *arr, int size, int weight)
{
    assert(arr);
    int begin = 0;
    int sum = 0;
    stack<int> s;
    int pos = 0;
    while (begin < size)
    {
        if (pos < size)
        {
            s.push(pos);
            sum += arr[pos];
            if (sum == weight)
            {
                Print(arr, s);

            }
            if (sum > weight)
            {
                sum -= arr[s.top()];
                s.pop();
            }
            pos++;
        }
        else
        {
            sum -= arr[s.top()];
            pos = s.top() + 1;
            s.pop();
        }

        if (s.empty())
        {
            begin++;
            pos = begin;
            sum = 0;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值