棧和隊列的面試題Java

棧和隊列:

  面試的時候,棧和隊列常常會成對出現來考察。本文包含棧和隊列的以下考試內容:java

  (1)棧的建立node

  (2)隊列的建立面試

  (3)兩個棧實現一個隊列數組

  (4)兩個隊列實現一個棧微信

  (5)設計含最小函數min()的棧,要求min、push、pop、的時間複雜度都是O(1)函數

  (6)判斷棧的push和pop序列是否一致this

1. 棧的建立:

咱們接下來經過鏈表的形式來建立棧,方便擴充。設計

代碼實現:3d

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 }

入棧操做時,1四、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. 兩個隊列實現一個棧:

思路:

  將一、二、3依次入隊列一, 而後最上面的3留在隊列一,將下面的二、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

六、判斷棧的push和pop序列是否一致:

通俗一點講:已知一組數據一、二、三、四、5依次進棧,那麼它的出棧方式有不少種,請判斷一下給出的出棧方式是不是正確的?

例如:

數據:

  一、二、三、四、5

出棧1:

  五、四、三、二、1(正確)

出棧2:

  四、五、三、二、1(正確)

出棧3:

  四、三、五、一、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

相關文章
相關標籤/搜索