腾讯电话面试

今天内推腾讯实习生一面html

其中问道一个问题是,怎样在不消除递归的状况下防止栈溢出?(不管如何都要使用递归)面试

面试的时候,一点都不知道,只能说使用循环来消除,可是那样不知足要求,后来看看这篇博客http://blog.zhaojie.me/2009/03/tail-recursion-and-continuation.html 才懂了。算法

还有一个不知道的问题是优先队列的实现,原来没有接触过这种数据结构,因此当时想了半天也不知道。。编程

看《数据结构与算法分析——C语言描述》中有提到,结果发现是我本身没有理解题目的意思。数组

实现方式能够见链接:http://www.cnblogs.com/wuchanming/p/3809496.html数据结构

《编程之美》中有这样一个题目:数据结构和算法

队列中取最大值操做问题,题目描述:spa

假设有这样一个拥有3个操做的队列:设计

1 Enqueue(v): 将v加入队列指针

2 DeQueue:使队列中的队首元素删除并返回此元素

3 MaxElement:返回队列中的最大元素

请设计一种数据结构和算法,让MaxElement操做的时间复杂度尽量地低。

队列是遵照“先入先出”原则的一种复杂数据结构。其底层的数据结构不必定要用数组来实现,还可使用其余特殊的数据结构来实现,以达到下降MaxElement操做复杂度的目的。

分析与解法:

解法一

这个问题的关键在于取最大值的操做,而且考虑但队列里面的元素动态增长和减小的时候,如何可以很是快速地把最大值取出。

虽然,最直接的思路就是按传统方式来实现队列。利用一个数组或链表来存储队列的元素,利用两个指针分别指向队列的队首和队尾。若是采用这种方法,那么MaxElement操做须要遍历队列的全部元素。在队列的长度为N的条件下,时间复杂度为O(N)。

解法二

根据取最大值的要求,能够考虑用最大堆来维护队列中的元素。堆中每一个元素都有指针指向它的后续元素。这样,堆就能够很快实现返回最大元素的操做。同时,咱们也能保证队列的正常插入和删除。MaxElement操做其实就是维护一个最大堆,其时间复杂度为O(1)。而入队和出队操做的时间复杂度为O(lgN)

开始不太能理解,后来想一想好像是这样的,好比,队列是先进先出的,因此用一种数据结构来记录元素的进出顺序,而使用最大堆来维持找到最大值的效率。假如使用queue来存放全部的数据,当入队的时候直接插入队尾,而最大堆也须要将加入的值放在堆的最后,而后进行调整,直到知足最大堆。若是是进行访问最大值,能够直接访问堆顶的元素。若是是进行出队操做,从队列的首部删除该元素,并在最大堆中找到该元素,删除以后,进行调整。这样既可以达到知足队列的“先进先出”,也能知足在O(1)的条件下访问到最大值。

解法三

曾经作过一种相似的题目是最小栈,也就是在O(1)的状况下访问到栈中的最小元素。如是想到也可使用这种方式来实现优先队列,

若是使用两个数组分别存放,第一个数组按进入的顺序存放全部的元素,另外一个数组中存放最大值的下标,另外还用一个变量记录当前的最大值下标。

实现代码:

class stack
{
public:
    stack()
    {
        stackTop=-1;
        maxStackItemIndex=-1;
    }
    void push(Type x)
    {
        stackTop++;
        if(stackTop>=Max)
        ;  //栈满
        else
        {
            stackItem[stackTop]=x;
            if(x>Max())
            {
                link2NextMaxItem[stackTop]=maxStackItemIndex;
                maxStackItemIndex=stackTop;
            }
            else
                link2NextMaxItem[stackTop]=-1;
         }
    }
    Type Pop()
    {
        Type ret;
        if(stackTop<0)
            ThrowException();  //已经没有元素来,因此不能pop
        else
        {
            ret=stackItem[stackTop];
            if(stackTop==maxStackItemIndex)
            {
                maxStackItemIndex=link2NextMaxItem[stackTop];
            }
            stackTop--;
        }
        return ret;
    }
    Type Max()
    {
        if(maxStackItemIndex>=0)
            return stackItem[maxStackItemIndex];
        else
            return -INF;
    }
private:
    Type stackItem[MAXN];
    int stackTop;
    int link2NextMaxItem[MAXN];
    int maxStackItemIndex;
};

这里,维护一个最大值的序列来保证Max操做的时间复杂度为O(1),至关于用空间复杂度换取了时间复杂度。

若是可以用栈有效第实现队列,而栈的Max操做又很容易,那么队列的Max操做也就能有效地完成了。

相关文章
相关标签/搜索