程式設計師程式碼面試指南 —— 棧和佇列(一)
阿新 • • 發佈:2018-11-28
注:題目來自於《程式設計師程式碼面試指南:IT名企演算法與資料結構題目最優解》,該書是左程雲老師的著作,值得推薦,這裡僅是記錄一下該書中題目的解法和個人理解
一:設計一個有getMin功能的棧
題目:在實現棧的基本功能的基礎上,再實現返回棧中的最小元素操作
思路:可以建立一個輔助棧,輔助棧保證棧頂值既為最小值。
當入棧的元素小於輔助棧棧頂值,則輔助棧和資料棧都進行入棧操作。
當入棧的元素大於輔助棧棧頂值,則資料棧進行入棧操作輔助棧將棧頂元素複製一份,再將該元素進行入棧
圖解:
程式碼:
class MyStack { private Stack<Integer> stackData; private Stack<Integer> stackMin; public MyStack() { stackData = new Stack<>(); stackMin = new Stack<>(); } public void push(int num) { if (stackMin.isEmpty()) { stackMin.push(num); } else if (num < getMin()) { stackMin.push(num); } else { int c = stackMin.peek(); stackMin.push(c); } stackData.push(num); } public int pop() { if (stackData.isEmpty()) { throw new RuntimeException("stack is empty"); } else { stackMin.pop(); return stackData.pop(); } } public int getMin() { if (stackMin.isEmpty()) { throw new RuntimeException("stack is empty"); } else { return stackMin.peek(); } } }
測試方法:
public class GetMinStack { public static void main(String[] args) { MyStack stack = new MyStack(); stack.push(4); stack.push(3); stack.push(4); stack.push(1); stack.push(2); stack.pop(); stack.pop(); System.out.println("min is "+stack.getMin()); } }
執行結果,親測可用:
min is 3
二:由兩個棧組成的佇列
題目:編寫一個類,用兩個棧實現佇列,支援棧的基本操作(add、poll、peek)
思路:棧是先進後出,佇列是先進先出,所以剛好可以用兩個棧來實現這種資料結構
但是在資料彈出和壓入到另一個棧的時候,需要注意兩個點,如果stackPush要往stackPop壓入資料,
那麼必須保證一次把stackPush中的資料全部壓入stackPop。如果stackPop不為空,stackPush不允許向stackPop壓入資料
圖示:
程式碼:
class TwoStactQueue { public Stack<Integer> stackPush; public Stack<Integer> stackPop; public TwoStactQueue() { stackPop = new Stack<>(); stackPush = new Stack<>(); } public void add(int num) { stackPush.push(num); } public int poll() { if (stackPop.isEmpty() && stackPush.isEmpty()) { throw new RuntimeException("Queue is empty"); } else if (stackPop.isEmpty()) { while (!stackPush.empty()) { stackPop.push(stackPush.pop()); } } return stackPop.pop(); } public int peek() { if (stackPop.isEmpty() && stackPush.isEmpty()) { throw new RuntimeException("Queue is empty"); } else if (stackPop.isEmpty()) { while (!stackPush.empty()) { stackPop.push(stackPush.pop()); } } return stackPop.peek(); } }
測試類:
public class StackToQueue {
public static void main(String[] args) {
TwoStactQueue queue = new TwoStactQueue();
queue.add(1);
queue.add(2);
queue.add(3);
System.out.println(queue.poll() + "," + queue.poll());
queue.add(4);
queue.add(5);
System.out.println(queue.poll() + "," + queue.peek() + "," + queue.poll());
}
}
執行結果,親測可用:
1,2
3,4,4
三:如何僅用遞迴函式和棧操作逆序一個棧
題目:將一個棧中的內容逆序輸出,只用遞迴函式來實現
思路:可以用兩個遞迴函式來實現
第一個遞迴函式用來將棧底數字取出,第二個遞迴函式用來將數字入棧
圖示:
程式碼:
public class ReverStack {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(3);
stack.push(2);
stack.push(1);
reverse(stack);
System.out.println(stack.toString());
}
/**
* 將棧stack的棧底元素返回並移除
*
* @return 棧底元素
*/
public static int getAndRemoveLastElement(Stack<Integer> stack){
int result = stack.pop();
if(stack.isEmpty()){
return result;
}else{
int last = getAndRemoveLastElement(stack);
stack.push(result);
return last;
}
}
public static void reverse(Stack<Integer> stack){
if(stack.isEmpty()){
return;
}
int i = getAndRemoveLastElement(stack);
reverse(stack);
stack.push(i);
}
}
測試結果,親測可用:
[1, 2, 3]