zoukankan      html  css  js  c++  java
  • 栈和队列的面试题Java

    栈和队列:

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

      (1)栈的创建

      (2)队列的创建

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

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

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

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

    1. 栈的创建:

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

    代码实现:

     1 public class Stack {
     2 
     3     public Node head;
     4     public Node current;
     5 
     6 
     7     //方法:入栈操作
     8     public void push(int data) {
     9         if (head == null) {
    10             head = new Node(data);
    11             current = head;
    12         } else {
    13             Node node = new Node(data);
    14             node.pre = current;//current结点将作为当前结点的前驱结点
    15             current = node;  //让current结点永远指向新添加的那个结点
    16         }
    17     }
    18 
    19     public Node pop() {
    20         if (current == null) {
    21             return null;
    22         }
    23 
    24         Node node = current; // current结点是我们要出栈的结点
    25         current = current.pre;  //每出栈一个结点后,current后退一位
    26         return node;
    27 
    28     }
    29 
    30 
    31     class Node {
    32         int data;
    33         Node pre;  //我们需要知道当前结点的前一个结点
    34 
    35         public Node(int data) {
    36             this.data = data;
    37         }
    38     }
    39 
    40 
    41     public static void main(String[] args) {
    42 
    43         Stack stack = new Stack();
    44         stack.push(1);
    45         stack.push(2);
    46         stack.push(3);
    47 
    48         System.out.println(stack.pop().data);
    49         System.out.println(stack.pop().data);
    50         System.out.println(stack.pop().data);
    51     }
    52 
    53 }
    
    

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

    运行效果:

    result

    2. 队列的创建:

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

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

    代码实现:

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

     1 public class Queue {
     2     public Node head;
     3     public Node curent;
     4 
     5     //方法:链表中添加结点
     6     public void add(int data) {
     7         if (head == null) {
     8             head = new Node(data);
     9             curent = head;
    10         } else {
    11             curent.next = new Node(data);
    12             curent = curent.next;
    13         }
    14     }
    15 
    16     //方法:出队操作
    17     public int pop() throws Exception {
    18         if (head == null) {
    19             throw new Exception("队列为空");
    20         }
    21 
    22         Node node = head;  //node结点就是我们要出队的结点
    23         head = head.next; //出队之后,head指针向下移
    24 
    25         return node.data;
    26 
    27     }
    28 
    29 
    30     class Node {
    31         int data;
    32         Node next;
    33 
    34         public Node(int data) {
    35             this.data = data;
    36         }
    37     }
    38 
    39 
    40     public static void main(String[] args) throws Exception {
    41         Queue queue = new Queue();
    42         //入队操作
    43         for (int i = 0; i < 5; i++) {
    44             queue.add(i);
    45         }
    46 
    47         //出队操作
    48         System.out.println(queue.pop());
    49         System.out.println(queue.pop());
    50         System.out.println(queue.pop());
    51 
    52     }
    53 }
    

    运行效果:

    result

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

    思路:

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

    用栈1负责来添加操作,用栈2来实现弹出操作;如果栈2里面有元素,直接弹出,没有元素,判断栈1,栈1没有元素,返回错误;栈1有元素,则将栈1里面的元素都弹到栈2,然后从栈2中弹出元素。

    完整版代码实现:

     1 import java.util.Stack;
    
     6 public class Queue {
     7 
     8     Stack<Integer> stack1 = new Stack<Integer>();
           Stack<Integer> stack2 = new Stack<Integer>();
     10	/**
     11	 * 每次添加都往栈1里面添加
     12	 * @param node 待插入队列中元素
     13	 */
     14	public void push(int node){
     15	    stack1.push(node);
     16	}
     17	
     18	/**
     19	 * 每次弹出都从栈2里面弹出
     20	 * @return
    	 */
    	public int pop(){
    	    if(!stack2.isEmpty())
    	        return stack2.pop();
    	    if(stack1.isEmpty())
    	        return -1;
    	    else{
    	    	while(!stack1.isEmpty())
    	            stack2.push(stack1.pop());
                return stack2.pop();
                }
    	}
    37     public static void main(String[] args) throws Exception {
    38         Queue queue = new Queue();
    39         queue.push(1);
    40         queue.push(2);
    41         queue.push(3);
    42 
    43         System.out.println(queue.pop());
    44 
    45         queue.push(4);
    46 
    47         System.out.println(queue.pop());
    48         System.out.println(queue.pop());
    49         System.out.println(queue.pop());
    50 
    51     }
    52 
    53 }
    

    运行效果:

    result

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

    思路:

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

    代码实现:

     1 import java.util.ArrayDeque;
     2 import java.util.Queue;
     3 
     
     7 public class Stack {
     8 
    	Queue queue1 = new LinkedList();
    	Queue queue2 = new LinkedList();
    11 
    12   /**
    	 * 添加元素的时候向不为空的队列中添加元素
    	 * @param node
    	 */
    	public void push(int node){
    	    if(queue2.isEmpty())
    	        queue1.add(node);
    	    if(queue1.isEmpty())
    	        queue2.add(node);
                }
    	
    	/**
    	 * 删除元素的时候先将不为空的队列的前n-1个元素添加到另外一个队列中,然后将第n个元素删除
    	 * @return
    	 */
    	public int poll(){
    		int temp = -1;
    		if(!queue2.isEmpty()){
    		while(!queue2.isEmpty()){
    		    temp = (int) queue2.poll();
    		    if(!queue2.isEmpty())
    			queue1.add(temp);
    		    }
    		    return temp;
    		}else if(!queue1.isEmpty()){
    		    while(!queue1.isEmpty()){
    		        temp = (int) queue1.poll();
    		        if(!queue1.isEmpty())
        			    queue2.add(temp);
    		    }
    		    return temp;
    		}else
    		    return -1;
    	}
    36 
    37     public static void main(String[] args) throws Exception {
    38         Stack stack = new Stack();
    39 
    40         stack.push(1);
    41         stack.push(2);
    42         stack.push(3);
    43 
    44         System.out.println(stack.pop());
    45         System.out.println(stack.pop());
    46         stack.push(4);
    47     }
    48 }
    
    

    运行效果:

    result

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

    普通思路:

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

    改进思路:

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

    完整代码实现:

    
     1 import java.util.Stack;
     2 
     6 public class MinStack {
     7 
     8    
            Stack stack = new Stack();     //定义用来存储数据的栈
            Stack minStack = new Stack();  //定义用来存储最小数据的栈
    	    
            /**
             * 添加数据,首先是往stack栈中添加
             * 如果最小栈minStack为空,或者栈顶的元素比新添加的元素要大,则将新元素也要添加的辅助栈中
             * @param node
             */
            public void push(int node) {
                stack.push(node);
                if(minStack.isEmpty() || ((int)minStack.peek()) >= node){
                	minStack.push(node);
                }
            }
    	    
            /**
             * 如果stack空,直接返回
             * 如果stack不为空,得到栈顶元素,同时将栈顶元素弹出
             * 如果最小栈的栈顶元素与stack弹出的元素相等,那么最小栈也要将其弹出
             */
            public void pop() {
                if(stack.isEmpty())
                    return;
                int node = (int)stack.peek();
                stack.pop();
                if((int)minStack.peek() == node){
                    minStack.pop();
                }
            }
    	    
            /**
             * 查看栈顶元素
             * @return
             */
            public int top() {
                return (int)stack.peek();
            }
            
            /**
             * 查看栈的最小元素
             * @return
             */
            public int min() {
                return (int)minStack.peek();
            }
         
    40     public static void main(String[] args) throws Exception {
    41         MinStack stack = new MinStack();
    42         stack.push(4);
    43         stack.push(3);
    44         stack.push(5);
    45 
    46         System.out.println(stack.min());
    47     }
    48 }
    
    

    result

    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(错误)

    完整版代码:

    
     1 import java.util.Stack;
     2 
     3 /**
     4  * Created by smyhvae on 2015/9/9.
     5  */
     6 public class StackTest {
     7 
     8 /**
         * 首先将特殊情况,边界情况进行排除掉
         * 然后定义一个循环,开始遍历第一个数组,将遍历的每个对象往stack里面添加,
         * 如果遇到栈不为空且stack顶元素与第二个数组对应位置相等的情况,就弹栈,
         * 同时第二个数组指针后移
         * 最后判断栈是否为空
         * @param pushA 入栈队列
         * @param popA  出栈队列
         * @return
         */
        public boolean isPopOrder(int[] pushA, int[] popA){
        	if(pushA == null || popA == null || pushA.length == 0 || popA.length == 0 || pushA.length != popA.length)
        		return false;
        	if(pushA.length == popA.length && pushA.length == 1)
        		return pushA[0] == popA[0];
        	Stack stack = new Stack();
        	int i = 0;
        	int j = 0;
        	int len = pushA.length;
        	while(i < len && j < len){
        		stack.push(pushA[i]);
        		++i;
        		while(!stack.isEmpty() && (int)stack.peek() == popA[j]) {
        			stack.pop();
        			++j;
        		}
        	}
        	return stack.isEmpty();
        }
    24 
    25     public static void main(String[] args) {
    26 
    27         Stack<Integer> stack = new Stack<Integer>();
    28 
    29         int[] data1 = {1, 2, 3, 4, 5};
    30         int[] data2 = {4, 5, 3, 2, 1};
    31         int[] data3 = {4, 5, 2, 3, 1};
    32 
    33         System.out.println(sequenseIsPop(data1, data2));
    34         System.out.println(sequenseIsPop(data1, data3));
    35     }
    36 }
    
    

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

    运行效果:

    result

  • 相关阅读:
    Learning NFS/NIS 2nd 读书笔记-Chapter3 NIS Operation
    Linux Enterprise Cluster Notes Ch11 LVS Introduction Theory
    Linux Enterprise Cluster NOtes Ch7 A Sample HA config
    Linux Enterprise Cluster Notes Ch10 build a Linux cluster
    Linux Enterprise Cluster NOtes Ch8 Heartbeat配置和维护
    当被监控的应用发生问题时,heartbeat会failover么?
    Linux Enterprise Cluster NOtes Ch9 Stonith and IPFail
    Linux Enterprise Cluster NOtes Ch6 Heartbeat介绍和原理
    客户端不支持javascript怎么办
    js 返回对象|js返回多个值的方法|js如何返回多个值
  • 原文地址:https://www.cnblogs.com/wzyxidian/p/5931516.html
Copyright © 2011-2022 走看看