如何僅用遞迴函式和棧操作逆序一個棧

weixin_33936401發表於2017-11-29

本題來自程式設計師程式碼面試指南


題目

一個棧依次壓入1、2、3、4、5,那麼從棧頂到棧底分別為5、4、3、2、1。將這個棧轉置後,從棧頂到棧底為1、2、3、4、5,也就是實現棧中元素的逆序,但是隻能用遞迴函式來實現,不能用其他資料結構。

  • 遞迴函式一:將棧stack的棧底元素返回並移除


    3782250-d9ac7226824a3b61.png
    遞迴函式一
  • 遞迴函式二:逆序一個棧,就是題目要求實現的方法,具體過程就是如下程式碼中的reverse方法。


    3782250-ffca7ad43abbd3fc.png
    遞迴函式二
public class ReverseStack {

    /**
     * 將棧的棧底元素出棧返回
     * @param stack
     * @param <T>
     * @return
     */
    public static <T> T getAndRemoveLastElement(Stack<T> stack) {
        //講一個值彈出棧
        T result = stack.pop();
        //棧空返回棧底元素
        if (stack.isEmpty()) {
            return result;
        } else {
            //在遞迴呼叫的過程中棧底元素始終保持在last裡
            T last = getAndRemoveLastElement(stack);
            //呼叫返回,將非棧底元素重新壓入棧中
            stack.push(result);
            return last;
        }
    }

    /**
     * 將棧逆序
     * @param stack
     * @param <T>
     */
    public static <T> void reverse(Stack<T> stack) {
        //遞迴呼叫的返回條件
        if (stack.isEmpty()) {
            return;
        }
        //返回棧中最後一個值
        T andRemoveLastElement = getAndRemoveLastElement(stack);
        reverse(stack);
        stack.push(andRemoveLastElement);
    }
}

遞迴看起來就像玄學,這個題在遞迴中套個遞迴,看上去就很有意思。
倆個遞迴分開看 ,第一個先將棧中元素彈出一個存到變數中,遞迴返回條件是彈出一個元素後棧空將棧底元素作為返回值返回,回到呼叫流程後將存在變數中的非棧底元素再次壓入棧中;第二個的返回條件是棧空,而第二個每一步彈出的是棧底元素,通過這個方法實現棧的逆序。

最後附上github地址

相關文章