在大学学过数据结构课的人相信都对这样一个问题不陌生,描述大致如下:
某个程序可以进行一系列入栈和出栈的混合操作。每次入栈操作将整数0到9中的一个元素按顺序压入栈,出栈操作打印弹出栈顶的整数。问给出的一个打印序列是否合法。
这道题应该是数据结构考试的一道经典问题了。如果是在卷面上作答,我的做法是在纸上写下所给的序列,同时画一个空栈。然后将序列和栈顶元素“对拍”。如果无法从栈中弹出序列的当前元素,那么就是不合法的;对拍完成就是合法的。
如果是编写程序实现呢,其实完全去模拟手工实现的方法就可以。
今天读普利斯顿大学的那本橙色的《算法》书,在练习1.3.3中再次遇到了这道题,于是第一次编程实现了。代码如下。
1 package exercises; 2 3 import edu.princeton.cs.algs4.Queue; 4 import edu.princeton.cs.algs4.Stack; 5 import edu.princeton.cs.algs4.StdOut; 6 7 /** 8 * @author Helena Wang 9 * @version 0.0.1 10 * @function 判断是否是合法的栈混洗序列 11 * @time 2018/7/18 16:50 12 */ 13 public class StackOrderValidation {//TODO:write a blog 14 private Stack<Integer> stack; 15 private Queue<Integer> queue; 16 public StackOrderValidation() { 17 18 } 19 public boolean validate(String string) { 20 stack = new Stack<>(); 21 queue = new Queue<>(); 22 String[] str = string.split(" "); 23 for (String s: str) { 24 queue.enqueue(Integer.parseInt(s)); 25 } 26 int cur = -1; //当前入过栈的最大元素 27 while (!queue.isEmpty()) { 28 // StdOut.println(queue); 29 while (cur < queue.peek()) {//尝试让栈顶和队列头的元素匹配 30 cur++; 31 stack.push(cur); 32 } 33 34 if (queue.peek().equals(stack.peek())) { //匹配上,抵消掉 35 queue.dequeue(); 36 stack.pop(); 37 } else return false;//下一个元素不在栈顶,被压着,序列不可能 38 } 39 return true; 40 } 41 42 public static void main(String[] args) { 43 StackOrderValidation sov = new StackOrderValidation(); 44 String[] strings = { //测试用例出自《算法4th》练习1.3.3 45 "4 3 2 1 0 9 8 7 6 5", 46 "4 6 8 7 5 3 2 9 0 1", 47 "2 5 6 7 4 8 9 3 1 0", 48 "4 3 2 1 0 5 6 7 8 9", 49 "1 2 3 4 5 6 9 8 7 0", 50 "0 4 6 5 3 8 1 7 2 9", 51 "1 4 7 9 8 6 5 3 0 2", 52 "2 1 4 3 6 5 8 7 9 0" 53 }; 54 for (int i=0; i<strings.length; i++) { 55 StdOut.println(strings[i] + "===================="); 56 StdOut.println(i + ": " + sov.validate(strings[i])); 57 } 58 } 59 }