一個棧依次壓入1、2、3、4、5,那么從棧頂?shù)綏5追謩e為5、4、3、2、1。將這個棧轉(zhuǎn)置后,從棧頂?shù)綏5诪?、2、3、4、5,也就是實現(xiàn)了棧中元素的逆序,請設計一個算法實現(xiàn)逆序棧的操作,但是只能用遞歸函數(shù)來實現(xiàn),而不能用另外的數(shù)據(jù)結(jié)構(gòu)。
看到這個題首先想到的就是新建一個棧,前一個棧每pop出一個元素,就將這個元素push進新棧中,這樣很容易就實現(xiàn)了棧的逆序,但是題干中已經(jīng)明確說明這么做是不行滴,必須用遞歸來做。事實上函數(shù)遞歸底層也是由系統(tǒng)維護的函數(shù)棧進行一系列的push和pop操作,只是這個棧不需要我們手動維護。
對于遞歸實現(xiàn),解決該題需要分為如下兩個步驟:
- 實現(xiàn)
getAndRemoveLastElement()
用來抽出stack的棧底元素并返回 - 遞歸調(diào)用
reverseStackRecursively()
函數(shù),每次從棧中抽出底部元素,直到把棧抽空,再回溯反壓入棧
代碼如下
import java.util.Stack;
/**
* Created by wangshiyi on 17/7/26.
*
* 只用遞歸函數(shù)實現(xiàn)棧的逆序
*/
public class ReverseStack {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
System.out.println("原始棧:" + stack); // [1, 2, 3, 4, 5]
reverseStackRecursively(stack);
System.out.println("逆序后的棧:" + stack); // [5, 4, 3, 2, 1]
}
/**
* 遞歸實現(xiàn)棧的逆序
*
* @param stack
*/
public static void reverseStackRecursively(Stack<Integer> stack) {
if (stack.isEmpty()) { // 已把棧抽空,開始回溯(反壓)
return;
}
int i = getAndRemoveLastElement(stack);
reverseStackRecursively(stack);
stack.push(i); // 把抽出的元素反壓入棧
}
/**
* 移除stack的棧底元素,其他元素不變
*
* @param stack
* @return 返回所移除的棧底元素
*/
public static int getAndRemoveLastElement(Stack<Integer> stack) {
int result = stack.pop();
if (stack.isEmpty()) { // 如果result為棧底元素,將棧底元素回溯
return result;
} else {
int last = getAndRemoveLastElement(stack); // 拿到棧底元素
stack.push(result); // push回之前pop的元素
return last;
}
}
}
牛客網(wǎng)上有該題的練習,只不過是用數(shù)組來描述棧的,對于實現(xiàn)getAndRemoveLastElement()
反而更簡單,傳送門
另外此前做過一些有關(guān)棧的題目,用兩個棧模擬實現(xiàn)一個隊列、Pop Sequence、表達式求值,都是筆試面試中常見的問題。