数据结构之栈和队列
第一篇:数据结构之链表
这次,我们主要看栈和队列的相关题目。
栈是“后进先出”的数据结构,队列是“先进先出”的数据结构,我们假设栈和队列中存储的都是整型数值,先来定义这两种数据结构(都采用数组的形式来存储信息,当达到数组边界时,对数组进行扩容处理)。
栈主要包括Push、Pop和Peek和Count三个方法,如下:
栈的定义
队列主要包括EnQueue和DeQueue两个方法,如下:
队列的定义
下面,我们来看和这两种数据类型相关的题目。
- 设计含有min函数的栈,要求min、push和pop的时间复杂度是O(1)。
思路:使用一个栈来实现上述要求,在栈顶保存min()值,每次Push或者Pop,向栈操作两次,第一次针对min,第二次是实际的值,这样我们可以使用Peek方法来取得min值。
含有min的栈上述代码是从头开始实现的栈,包括对存储结构的处理细节,我们可以看上面关于Stack的定义,其实已经包括了这些细节,因此我们可以直接拿来用,代码会更清晰。
含有min的栈 - 用两个栈实现一个队列
思路:两个栈一个作为入值栈,一个作为出值栈,当执行Push操作时,将值压入入值栈,当执行Pop或者Peek操作时,取出值栈的栈顶元素,当出值栈为空时,需要将入值栈的元素依次压入出值栈。
两个栈表示一个队列 - 用两个队列实现一个栈
思路:根据“后进先出”和“先进后出”的特点,在运行过程中,其中一个队列应该一直为空,对于push操作,将值放到非空队列中,当进行Push或者Pop操作时,先将非空队列全部导入空队列,然后此时的非空队列的头元素就是我们期望的元素。
两个队列表示一个栈 - 递归反转一个栈,要求不能重建一个新栈,空间复杂度为O(1)。
思路:参考汉诺塔的递归思路。
反转一个栈 - 对栈进行排序
思路:依旧采取递归的套路
对栈内元素进行排序 - 判断栈的push、pop序列是否一致
思路:创建一个新栈,依次将push队列中的值压入,在压入过程中,判断pop队列,如果找到相同的值,执行stack.pop操作,以此类推,最终判断stack是否为空。
View Code - 如何用一个数组实现两个栈
思路:用0、2、4、6……表示第一个栈的元素,用1、3、5、7表示第二个栈的元素
一个数组表示两个栈这种方式在两个栈的容量接近时比较好,如果两个栈的容量相差很大, 那么会浪费很多存储空间。针对这个问题的解决方法是用0、1、2、3……表示第一个栈,用n、n-1、n-2、n-3……表示第二个栈,代码实现类似,这种情况下也可以对数组进行扩容。
最后,欢迎大家提出更多相关的面试题目,我们可以一起讨论。