"Coding Interview Guide" -- 仅用递归函数和栈操作逆序一个栈
【题目】
一个栈依次压入1、2、3、4、5,那么从栈顶到栈底分别为5、4、3、2、1。将这个栈转置后,从栈顶到栈底为1,2,3,4,5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能使用其它数据结构
【分析】
栈是一种操作受限的数据结构,只能从某一端进行插入和删除和访问元素。能进行插入删除和访问等操作的一端称为“栈顶”,相对的另一端,不能进行任何栈操作,称为栈底。栈中除了栈顶元素外,其它的栈元素都是不允许访问的。所以想要访问栈中其它元素,则只能将将栈中元素依次弹出直到该元素成为栈顶元素。
如果用一个递归函数来访问栈中元素,则可以实现从栈顶到栈底或者从栈底到栈顶的访问次序,这取决于你是在递归发生之前访问还是递归发生之后访问。一个递归函数可以以逆序的方式访问栈(即以从栈底到栈顶的次序访问栈元素),却不能实现将栈中元素逆序。此时,可以借助另外一个递归函数,试想,既然一个递归函数可以逆序访问栈,那用另外一个递归函数就可以将第一个递归得到的逆序元素序列再逆序压入栈中,例如栈中元素从栈顶到栈底元素分别为5、4、3、2、1,使用一个递归可以实现逆序访问,即1,2,3,4,5,然后用另外一个递归函数将1,2,3,4,5逆序压入栈中,注意是逆序,即第一个递归函数虽然最先访问1但是第二个递归函数却是将它最后压入栈。这样通过两个递归函数嵌套即可逆序一个栈。因为第二个递归要将元素逆序压入栈,则要求当第二个递归开始压入时栈应该是空的,那么怎么实现第一个递归逆序访问结束后栈变为空的呢?所以第一个递归所做的事情不只是逆序访问,它还要在访问时删除栈元素,所以第一个递归需要删除并返回当前栈的栈底元素。
import java.util.Stack;
1 public static int getAndRemoveLastElement(Stack<Integer> stack) // 第一个递归函数,即内层递归,移除并返回当前栈底元素,实现逆序访问 2 { 3 int value = stack.pop(); 4 if(stack.isEmpty()) //移除并返回当前栈中的栈底元素 5 { 6 return value; 7 } 8 else 9 { 10 int bottomCur = getAndRemoveLastElement(stack); 11 stack.push(value); // 对于当前栈中的非栈底元素仍让其留在栈中 12 return bottomCur; 13 } 14 } 15 16 public static void reverse(Stack<Integer> stack) // 第二个递归函数,即外层递归,实现对逆序元素序列再逆序进栈 17 { 18 if(stack.isEmpty()) // 如果第一个递归函数已经完成对栈中所有元素的逆序访问,则外层递归开始将元素逆序压入栈 19 { 20 return; 21 } 22 23 int cur = getAndRemoveLastElement(stack); 24 reverse(stack); 25 stack.push(cur); 26 } 27
来源:左程云老师《程序员代码面试指南》