棧和隊列的面試題Java實現【重要】

 

棧和隊列: java

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

  (1)棧的建立面試

  (2)隊列的建立數組

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

  (4)兩個隊列實現一個棧函數

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

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

 

一、棧的建立:設計

    咱們接下來經過鏈表的形式來建立棧,方便擴充。
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行代碼是關鍵。

運行效果:

e6e0ae76-0eed-4f1c-95a0-10e543237d63

  

二、隊列的建立:

  隊列的建立有兩種形式:基於數組結構實現(順序隊列)、基於鏈表結構實現(鏈式隊列)。

  咱們接下來經過鏈表的形式來建立隊列,這樣的話,隊列在擴充時會比較方便。隊列在出隊時,從頭結點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 }

運行效果:

fd770486-0cbe-45d8-96a7-0f3116045a35

  

三、兩個棧實現一個隊列:

思路:

    棧1用於存儲元素,棧2用於彈出元素,負負得正

    說的通俗一點,如今把數據一、二、3分別入棧一,而後從棧一中出來(三、二、1),放到棧二中,那麼,從棧二中出來的數據(一、二、3)就符合隊列的規律了,即負負得正。

完整版代碼實現:

 1 import java.util.Stack;
 2 
 3 /**
 4  * Created by smyhvae on 2015/9/9.
 5  */
 6 public class Queue {
 7 
 8     private Stack<Integer> stack1 = new Stack<>();//執行入隊操做的棧
 9     private Stack<Integer> stack2 = new Stack<>();//執行出隊操做的棧
10 
11 
12     //方法:給隊列增長一個入隊的操做
13     public void push(int data) {
14         stack1.push(data);
15 
16     }
17 
18     //方法:給隊列正價一個出隊的操做
19     public int pop() throws Exception {
20 
21 
22         if (stack2.empty()) {//stack1中的數據放到stack2以前,先要保證stack2裏面是空的(要麼一開始就是空的,要麼是stack2中的數據出完了),否則出隊的順序會亂的,這一點很容易忘
23 
24             while (!stack1.empty()) {
25                 stack2.push(stack1.pop());//把stack1中的數據出棧,放到stack2中【核心代碼】
26             }
27 
28         }
29 
30         if (stack2.empty()) { //stack2爲空時,有兩種可能:一、一開始,兩個棧的數據都是空的;二、stack2中的數據出完了
31             throw new Exception("隊列爲空");
32         }
33 
34         return stack2.pop();
35     }
36 
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 }

注意第22行和第30行代碼的順序,以及註釋,須要仔細理解其含義。

運行效果:

e5334faf-a36e-4aa2-9fe3-18157717bacd

  

四、兩個隊列實現一個棧:

思路:

  將一、二、3依次入隊列一, 而後最上面的3留在隊列一,將下面的二、3入隊列二,將3出隊列一,此時隊列一空了,而後把隊列二中的全部數據入隊列一;將最上面的2留在隊列一,將下面的3入隊列二。。。依次循環。

代碼實現:

 1 import java.util.ArrayDeque;
 2 import java.util.Queue;
 3 
 4 /**
 5  * Created by smyhvae on 2015/9/9.
 6  */
 7 public class Stack {
 8 
 9     Queue<Integer> queue1 = new ArrayDeque<Integer>();
10     Queue<Integer> queue2 = new ArrayDeque<Integer>();
11 
12     //方法:入棧操做
13     public void push(int data) {
14         queue1.add(data);
15     }
16 
17     //方法:出棧操做
18     public int pop() throws Exception {
19         int data;
20         if (queue1.size() == 0) {
21             throw new Exception("棧爲空");
22         }
23 
24         while (queue1.size() != 0) {
25             if (queue1.size() == 1) {
26                 data = queue1.poll();
27                 while (queue2.size() != 0) {  //把queue2中的所有數據放到隊列一中
28                     queue1.add(queue2.poll());
29                     return data;
30                 }
31             }
32             queue2.add(queue1.poll());
33         }
34         throw new Exception("棧爲空");//不知道這一行的代碼是什麼意思
35     }
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 }

運行效果:

7c0470f9-0558-4b00-9e04-51d018dd6081

  

五、設計含最小函數min()的棧,要求min、push、pop、的時間複雜度都是O(1)。min方法的做用是:就能返回是棧中的最小值。【微信面試題】

普通思路:

  通常狀況下,咱們可能會這麼想:利用min變量,每次添加元素時,都和min元素做比較,這樣的話,就能保證min存放的是最小值。可是這樣的話,會存在一個問題:若是最小的元素出棧了,那怎麼知道剩下的元素中哪一個是最小的元素呢?

改進思路:

    這裏須要加一個輔助棧,用空間換取時間。輔助棧中,棧頂永遠保存着當前棧中最小的數值。具體是這樣的:原棧中,每次添加一個新元素時,就和輔助棧的棧頂元素相比較,若是新元素小,就把新元素的值放到輔助棧中,若是新元素大,就把輔助棧的棧頂元素再copy一遍放到輔助棧的棧頂;原棧中,出棧時,

完整代碼實現:

 1 import java.util.Stack;
 2 
 3 /**
 4  * Created by smyhvae on 2015/9/9.
 5  */
 6 public class MinStack {
 7 
 8     private Stack<Integer> stack = new Stack<Integer>();
 9     private Stack<Integer> minStack = new Stack<Integer>(); //輔助棧:棧頂永遠保存stack中當前的最小的元素
10 
11 
12     public void push(int data) {
13         stack.push(data);  //直接往棧中添加數據
14 
15         //在輔助棧中須要作判斷
16         if (minStack.size() == 0 || data < minStack.peek()) { 17  minStack.push(data); 18         } else { 19             minStack.add(minStack.peek());   //【核心代碼】peek方法返回的是棧頂的元素
20  } 21     }
22 
23     public int pop() throws Exception {
24         if (stack.size() == 0) {
25             throw new Exception("棧中爲空");
26         }
27 
28         int data = stack.pop();
29         minStack.pop();  //核心代碼
30         return data;
31     }
32 
33     public int min() throws Exception {
34         if (minStack.size() == 0) {
35             throw new Exception("棧中空了");
36         }
37         return minStack.peek();
38     }
39 
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 }

604a9d9a-6e44-4cdf-ab4a-da3070e39ea1

  

六、判斷棧的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 
 9     //方法:data1數組的順序表示入棧的順序。如今判斷data2的這種出棧順序是否正確
10     public static boolean sequenseIsPop(int[] data1, int[] data2) {
11         Stack<Integer> stack = new Stack<Integer>(); //這裏須要用到輔助棧
12 
13         for (int i = 0, j = 0; i < data1.length; i++) {
14             stack.push(data1[i]);
15 
16             while (stack.size() > 0 && stack.peek() == data2[j]) { 17  stack.pop(); 18                 j++; 19  } 20         }
21         return stack.size() == 0; 22     }
23 
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 }

代碼比較簡潔,但也比較難理解,要仔細體會。

運行效果:

1cca8bbf-0eee-4049-88b6-d10a4f8c838a

 

個人公衆號

下圖是個人微信公衆號(生命團隊id:vitateam),歡迎有心人關注。博客園分享技術,公衆號分享心智

我會很感激第一批關注個人人。此時,年輕的我和你,一無全部;然後,富裕的你和我,滿載而歸。

相關文章
相關標籤/搜索