栈和队列:

面试的时候,栈和队列经常会成对出现来考察。本文包含栈和队列的如下考试内容:

  (1)栈的创建

  (2)队列的创建

  (3)两个栈实现一个队列

  (4)两个队列实现一个栈

  (5)设计含最小函数min()的栈,要求min、push、pop、的时间复杂度都是O(1)

  (6)判断栈的push和pop序列是否一致

1、栈的创建:

我们接下来通过链表的形式来创建栈,方便扩充。

代码实现:

 public class Stack {

     public Node head;
public Node current; //方法:入栈操作
public void push(int data) {
if (head == null) {
head = new Node(data);
current = head;
} else {
Node node = new Node(data);
node.pre = current;//current结点将作为当前结点的前驱结点
current = node; //让current结点永远指向新添加的那个结点

}
} public Node pop() {
if (current == null) {
return null;
} Node node = current; // current结点是我们要出栈的结点
current = current.pre; //每出栈一个结点后,current后退一位
return node; } class Node {
int data;
Node pre; //我们需要知道当前结点的前一个结点 public Node(int data) {
this.data = data;
}
} public static void main(String[] args) { Stack stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3); System.out.println(stack.pop().data);
System.out.println(stack.pop().data);
System.out.println(stack.pop().data);
} }

入栈操作时,14、15行代码是关键。

运行效果:

2、队列的创建:

  队列的创建有两种形式:基于数组结构实现(顺序队列)、基于链表结构实现(链式队列)。

  我们接下来通过链表的形式来创建队列,这样的话,队列在扩充时会比较方便。队列在出队时,从头结点head开始。

代码实现:

入栈时,和在普通的链表中添加结点的操作是一样的;出队时,出的永远都是head结点。

 public class Queue {
public Node head;
public Node curent; //方法:链表中添加结点
public void add(int data) {
if (head == null) {
head = new Node(data);
curent = head;
} else {
curent.next = new Node(data);
curent = curent.next;
}
} //方法:出队操作
public int pop() throws Exception {
if (head == null) {
throw new Exception("队列为空");
} Node node = head; //node结点就是我们要出队的结点
head = head.next; //出队之后,head指针向下移 return node.data; } class Node {
int data;
Node next; public Node(int data) {
this.data = data;
}
} public static void main(String[] args) throws Exception {
Queue queue = new Queue();
//入队操作
for (int i = 0; i < 5; i++) {
queue.add(i);
} //出队操作
System.out.println(queue.pop());
System.out.println(queue.pop());
System.out.println(queue.pop()); }
}

运行效果:

3、两个栈实现一个队列:

思路:

栈1用于存储元素,栈2用于弹出元素,负负得正

说的通俗一点,现在把数据1、2、3分别入栈一,然后从栈一中出来(3、2、1),放到栈二中,那么,从栈二中出来的数据(1、2、3)就符合队列的规律了,即负负得正。

完整版代码实现:

 import java.util.Stack;

 /**
* Created by smyhvae on 2015/9/9.
*/
public class Queue { private Stack<Integer> stack1 = new Stack<>();//执行入队操作的栈
private Stack<Integer> stack2 = new Stack<>();//执行出队操作的栈 //方法:给队列增加一个入队的操作
public void push(int data) {
stack1.push(data); } //方法:给队列正价一个出队的操作
public int pop() throws Exception { if (stack2.empty()) {//stack1中的数据放到stack2之前,先要保证stack2里面是空的(要么一开始就是空的,要么是stack2中的数据出完了),不然出队的顺序会乱的,这一点很容易忘 while (!stack1.empty()) {
stack2.push(stack1.pop());//把stack1中的数据出栈,放到stack2中【核心代码】
} } if (stack2.empty()) { //stack2为空时,有两种可能:1、一开始,两个栈的数据都是空的;2、stack2中的数据出完了
throw new Exception("队列为空");
} return stack2.pop();
} public static void main(String[] args) throws Exception {
Queue queue = new Queue();
queue.push(1);
queue.push(2);
queue.push(3); System.out.println(queue.pop()); queue.push(4); System.out.println(queue.pop());
System.out.println(queue.pop());
System.out.println(queue.pop()); } }

注意第22行和第30行代码的顺序,以及注释,需要仔细理解其含义。

运行效果:

4、两个队列实现一个栈:

思路:

  将1、2、3依次入队列一, 然后最上面的3留在队列一,将下面的2、3入队列二,将3出队列一,此时队列一空了,然后把队列二中的所有数据入队列一;将最上面的2留在队列一,将下面的3入队列二。。。依次循环。

代码实现:

 import java.util.ArrayDeque;
import java.util.Queue; /**
* Created by smyhvae on 2015/9/9.
*/
public class Stack { Queue<Integer> queue1 = new ArrayDeque<Integer>();
Queue<Integer> queue2 = new ArrayDeque<Integer>(); //方法:入栈操作
public void push(int data) {
queue1.add(data);
} //方法:出栈操作
public int pop() throws Exception {
int data;
if (queue1.size() == 0) {
throw new Exception("栈为空");
} while (queue1.size() != 0) {
if (queue1.size() == 1) {
data = queue1.poll();
while (queue2.size() != 0) { //把queue2中的全部数据放到队列一中
queue1.add(queue2.poll());
return data;
}
}
queue2.add(queue1.poll());
}
throw new Exception("栈为空");//不知道这一行的代码是什么意思
} public static void main(String[] args) throws Exception {
Stack stack = new Stack(); stack.push(1);
stack.push(2);
stack.push(3); System.out.println(stack.pop());
System.out.println(stack.pop());
stack.push(4);
}
}

运行效果:

5、设计含最小函数min()的栈,要求min、push、pop、的时间复杂度都是O(1)。min方法的作用是:就能返回是栈中的最小值。【微信面试题】

普通思路:

  一般情况下,我们可能会这么想:利用min变量,每次添加元素时,都和min元素作比较,这样的话,就能保证min存放的是最小值。但是这样的话,会存在一个问题:如果最小的元素出栈了,那怎么知道剩下的元素中哪个是最小的元素呢?

改进思路:

这里需要加一个辅助栈,用空间换取时间。辅助栈中,栈顶永远保存着当前栈中最小的数值。具体是这样的:原栈中,每次添加一个新元素时,就和辅助栈的栈顶元素相比较,如果新元素小,就把新元素的值放到辅助栈中,如果新元素大,就把辅助栈的栈顶元素再copy一遍放到辅助栈的栈顶;原栈中,出栈时,

完整代码实现:

 import java.util.Stack;

 /**
* Created by smyhvae on 2015/9/9.
*/
public class MinStack { private Stack<Integer> stack = new Stack<Integer>();
private Stack<Integer> minStack = new Stack<Integer>(); //辅助栈:栈顶永远保存stack中当前的最小的元素 public void push(int data) {
stack.push(data); //直接往栈中添加数据 //在辅助栈中需要做判断
if (minStack.size() == 0 || data < minStack.peek()) {
minStack.push(data);
} else {
minStack.add(minStack.peek()); //【核心代码】peek方法返回的是栈顶的元素
}
} public int pop() throws Exception {
if (stack.size() == 0) {
throw new Exception("栈中为空");
} int data = stack.pop();
minStack.pop(); //核心代码
return data;
} public int min() throws Exception {
if (minStack.size() == 0) {
throw new Exception("栈中空了");
}
return minStack.peek();
} public static void main(String[] args) throws Exception {
MinStack stack = new MinStack();
stack.push(4);
stack.push(3);
stack.push(5); System.out.println(stack.min());
}
}

6、判断栈的push和pop序列是否一致:

通俗一点讲:已知一组数据1、2、3、4、5依次进栈,那么它的出栈方式有很多种,请判断一下给出的出栈方式是否是正确的?

例如:

数据:

  1、2、3、4、5

出栈1:

  5、4、3、2、1(正确)

出栈2:

  4、5、3、2、1(正确)

出栈3:

  4、3、5、1、2(错误)

完整版代码:

 import java.util.Stack;

 /**
* Created by smyhvae on 2015/9/9.
*/
public class StackTest { //方法:data1数组的顺序表示入栈的顺序。现在判断data2的这种出栈顺序是否正确
public static boolean sequenseIsPop(int[] data1, int[] data2) {
Stack<Integer> stack = new Stack<Integer>(); //这里需要用到辅助栈 for (int i = 0, j = 0; i < data1.length; i++) {
stack.push(data1[i]); while (stack.size() > 0 && stack.peek() == data2[j]) {
stack.pop();
j++;
}
}
return stack.size() == 0;
} public static void main(String[] args) { Stack<Integer> stack = new Stack<Integer>(); int[] data1 = {1, 2, 3, 4, 5};
int[] data2 = {4, 5, 3, 2, 1};
int[] data3 = {4, 5, 2, 3, 1}; System.out.println(sequenseIsPop(data1, data2));
System.out.println(sequenseIsPop(data1, data3));
}
}

代码比较简洁,但也比较难理解,要仔细体会。

运行效果:

我的公众号

下图是我的微信公众号(生命团队id:vitateam),欢迎有心人关注。博客园分享技术,公众号分享心智

我会很感激第一批关注我的人。此时,年轻的我和你,一无所有;而后,富裕的你和我,满载而归。

栈和队列的面试题Java实现【重要】的更多相关文章

  1. 栈和队列的面试题Java

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

  2. 栈和队列的面试题Java实现

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

  3. 二叉树、栈、队列、链表的Java代码实现

    这是我的学习总结. 如有文章存在谬误,欢迎指出,有其他意见或者建议,也欢迎留言 二叉树链表 前序遍历:先访问根节点,然后访问左子树.右子树 中序遍历:先访问左子树,然后访问根节点.右子树 后序遍历:先 ...

  4. 剑指offer编程题Java实现——面试题7用两个栈实现队列

    题目:用两个栈实现一个队列.队列的声明如下:请实现他的两个函数appendTail和deleteHead, 分别完成在队列尾部插入节点和在队列头部删除节点的功能. package Solution; ...

  5. Java面试题:栈和队列的实现

    面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min()的栈,要 ...

  6. 剑指offer第二版面试题8:用两个栈实现队列(JAVA版)

    题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deletedHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能. 分析: 我们通过一个具体的例子来分析 ...

  7. java集合详解(附栈,队列)

    1 集合 1.1 为什么会出现集合框架 [1] 之前的数组作为容器时,不能自动拓容 [2] 数值在进行添加和删除操作时,需要开发者自己实现添加和删除. 1.2 Collection接口 1.2.1 C ...

  8. 【剑指offer】面试题 9. 用两个栈实现队列

    面试题 9. 用两个栈实现队列 题目描述 题目:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 解答过程 import java.util.Stack; publ ...

  9. Java:基于LinkedList实现栈和队列

    1.提供一组栈的接口,其底层关联到一个LinkedList(双端队列)实例.由于只暴露部分基于栈实现的接口,所以可以提供安全的栈实现. package junit; import java.util. ...

随机推荐

  1. 利用javascript、php和ajax实现计算器

    计算器和ajax部分: <?php /** * Created by PhpStorm. * User: Administrator * Date: 16-9-2 * Time: 上午9:20 ...

  2. jQuery pgwslideshow 空间相册

    一个响应式相册插件,你可以自定义幻灯片最大高度,滑动效果,是否显示控制按钮,自动轮播或间隔时间. pgwslideshow相册插件有以下特点    支持响应式    支持桌面和移动设备    代码简单 ...

  3. 本地Git服务器的搭建及使用

    本地Git服务器的搭建及使用 Git本地服务器环境搭建 搭建好的本地git服务器的局域网ip是192.168.1.188,用户名是RSCSVN 教程链接:http://blog.csdn.net/cc ...

  4. SAPScript、Smartforms动态打印图像或者背景图片

    在利用 SMARTFORMS 进行打印的时候有时候要求输出的图片可能是随着打印内容的不同而不同了,也就是动态输出图片,SMARTFORMS的提供了相关的支持技术,下面是实现截图 1.创建要显示的图片 ...

  5. 基于MATLAB实现的云模型计算隶属度

    ”云”或者’云滴‘是云模型的基本单元,所谓云是指在其论域上的一个分布,可以用联合概率的形式(x, u)来表示 云模型用三个数据来表示其特征 期望:云滴在论域空间分布的期望,一般用符号Εx表示. 熵:不 ...

  6. iOS开发工程师面试知识点汇总

    1.KVO实现原理 2.内存管理 3.Runtime 4.GCD 5.Block 6.响应者链 7.@peoperty属性特性 8.单元格cell加载图片处理

  7. Android 之 2048 的游戏逻辑分析

    继续学习了极客学院的实战路径课程,讲到了2048游戏的编写过程,我在这里作个总结分享给大家(结果会附源代码和我改写后的代码): 这里主要包括两个方面:1.2048界面的绘制   2.2048算法逻辑的 ...

  8. img标签使用默认图片的一种方式

    基于html5提供的onerror这个时间属性.

  9. Effective Java 65 Don't ignore exceptions

    Principle An empty catch block defeats the purpose of exceptions, which is to force you to handle ex ...

  10. js中 字符串与Unicode 字符值序列的相互转换

    一. 字符串转Unicode 字符值序列 var str = "abcdef"; var codeArr = []; for(var i=0;i<str.length;i++ ...