算法分析:两个栈实现一个队列

来源:互联网 发布:手机爱淘宝1元口令 编辑:程序博客网 时间:2024/04/28 06:29

两年前从网上看到一道面试题:用两个栈(Stack)实现一个队列(Queue)。觉得不错,就经常拿来面试,几年下来,做此题的应该有几十人了。通过对面试者的表现和反应,有一些统计和感受,在此做个小结。

 

用C++描述,题目大致是这样的:

 

已知下面Stack类及其3个方法Push、Pop和 Count,请用2个Stack实现Queue类的入队(Enqueue)出队(Dequeue)方法。

 

class Stack

{

public:

         void Push(int x); // Push an element in stack;

         int Pop();  // Pop an element out of stack;

         int Count() const;     // Return the number of the elements in stack;

};

 

class Queue

{

public:

         void Enqueue(int x);

         int Dequeue();

 

private:

         Stack s1;

         Stack s2;

};

 

这道题应该不算难,比起《编程之美》中微软那些什么“翻烙饼”的面试题,难度上差远了。况且,由于时间关系,我一般也不要求面试者写代码,只描述清楚思路即可。出这道题,主要考察3点:

 

1.       在短时间内,能不能找到解决这道题的足够清晰的思路(思维是否敏捷、清晰)。

2.       能不能在单向表述中,清楚地描述自己的思路和想法(表述能力是否达到要求)。

3.       对于某些具体细节,能不能考虑到(是否足够细致)。

 

总体上,以10人为例,实际的结果大致是:

 

1.       8个人可以找到解决答案,2个人无法找到答案(即使进行了必要的提示,曾经有位号称美国MIT深造2年,之后在Google美国公司工作过8个月的兄弟,也没做出来)。

2.       8个找到答案的人中,6个找到的方法相同,2个人找到其它变种。

3.       在这8个人中,有1个人可以不经提示,同时想到大众方法和变种。

 

大多数人的思路是:始终维护s1作为存储空间,以s2作为临时缓冲区。

入队时,将元素压入s1。

出队时,将s1的元素逐个“倒入”(弹出并压入)s2,将s2的顶元素弹出作为出队元素,之后再将s2剩下的元素逐个“倒回”s1。

见下面示意图:

 

2Stacks1Queue

 

上述思路,可行性毋庸置疑。但有一个细节是可以优化一下的。即:在出队时,将s1的元素逐个“倒入”s2时,原在s1栈底的元素,不用“倒入”s2(即只“倒”s1.Count()-1个),可直接弹出作为出队元素返回。这样可以减少一次压栈的操作。约有一半人,经提示后能意识到此问题。

 

上述思路,有些变种,如:

入队时,先判断s1是否为空,如不为空,说明所有元素都在s1,此时将入队元素直接压入s1;如为空,要将s2的元素逐个“倒回”s1,再压入入队元素。

出队时,先判断s2是否为空,如不为空,直接弹出s2的顶元素并出队;如为空,将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。

有些人能同时想到大众方法和变种,应该说头脑还是比较灵光的。

 

相对于第一种方法,变种的s2好像比较“懒”,每次出队后,并不将元素“倒回”s1,如果赶上下次还是出队操作,效率会高一些,但下次如果是入队操作,效率不如第一种方法。我有时会让面试者分析比较不同方法的性能。我感觉(没做深入研究),入队、出队操作随机分布时,上述两种方法总体上时间复杂度和空间复杂度应该相差无几(无非多个少个判断)。

 

真正性能较高的,其实是另一个变种。即:

入队时,将元素压入s1。

出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。

这个思路,避免了反复“倒”栈,仅在需要时才“倒”一次。但在实际面试中很少有人说出,可能是时间较少的缘故吧。

 

以上几个思路乍看没什么问题了,但其实还是有个细节要考虑的。其实无论什么方法和情况,都要考虑没有元素可供出队时的处理(2个栈都为空的时候,出队操作一定会引起异常)。在实际写代码时,忽略这些判断或异常处理,程序会出现问题。所以,能不能考虑到这些细节,也体现了个人的素养。

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 四川住房城乡建设厅 西安住房公积金管理中心 住房公积金贷款额度 沧州住房公积金查询 个人住房公积金查询入口 银行住房贷款利率计算器 合肥市住房公积金管理中心 山东省住房和城乡建设厅 2019商业住房贷款利率 住房和城乡建设部 长春住房公积金 四川省住房城乡建设厅首页 新乡市住房公积金管理中心 住房贷款利率计算器 邵阳市住房公积金管理中心 邵阳住房公积金 商业住房贷款利率 陕西省住房公积金管理中心 合肥住房公积金管理中心 长春市住房公积金 山东省住房城乡建设厅 2019各银行住房商贷利率一览表 住房公积金查询入口 陕西省住房和城乡建设厅网 沧州住房公积金个人查询入口 包头市住房公积金管理中心 佛山住房公积金中心 个人住房商业性贷款 住房公积金装修贷款能贷多少 邵阳住房公积金管理中心 工资4000住房公积金一般交多少 西安住房保障管理局网站 佛山住房公积金 住房城乡建设部 河南省住房和城乡建设厅网 北京住房公积金 广州住房公积金管理中心 西安住房公积金 成都住房公积金管理中心 宜春住房公积金 安徽省住房和城乡建设厅