假设某个用例程序会进行一系列入栈和出栈操作。入栈操作会将整数0到9按顺序压入栈;出栈操作会打印返回值。下面哪种顺序是不可能产生的?
(a) 4 3 2 1 0 9 8 7 6 5 (b) 4 6 8 7 5 3 2 9 0 1 (c) 2 5 6 7 4 8 9 3 1 0 (d) 4 3 2 1 0 5 6 7 8 9 (e) 1 2 3 4 5 6 9 8 7 0 (f) 0 4 6 5 3 8 1 7 2 9 (g) 1 4 7 9 8 6 5 3 0 2 (h) 2 1 4 3 6 5 8 7 9 0
分析3个数时的入栈与出栈操作,所有的顺序有3!种。分别为:
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
解法一
可以知道只有 3 1 2 这种顺序不可能的,将其推广就可以得到这种的规律:
大 小 中
这种顺序是不能出现的。
如上述中(b)中的9 0 1,(f)中的8 1 7,(g)中的3 0 2。所以b, f, g是不能产生的。
解法二
本文采用另一种思路来解决这个问题。
就假设上述都是合法序列,即都是由出栈产生的,那么应该能将些序列作为出入通过入栈与出栈操作,得到一个顺序的序列。
而问题在于入栈的方向、与得到顺序序列是升序还是降序呢?
显然逆过程应该是从上述输出的尾部开始入栈,而得到的序列应该也是逆序的。以(a)为例,从5开始入栈,一直到4。要得到9 8...1 0的序列。
下面给出实现的代码,首先需要给Stack添加一个top()方法。
/** * Description : * Author : mn@furzoom.com * Date : Sep 27, 2016 5:07:34 PM * Copyright (c) 2013-2016, http://furzoom.com All Rights Reserved. */ package com.furzoom.lab.algs.ch103; import java.util.Iterator; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; /** * ClassName : Stack <br> * Function : TODO ADD FUNCTION. <br> * date : Sep 27, 2016 5:07:34 PM <br> * * @version */ public class Stack<Item> implements Iterable<Item> { private Node first; private int n; private class Node { Item item; Node next; } public boolean isEmpty() { return first == null; } public int size() { return n; } public void push(Item item) { Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; n++; } public Item pop() { Item item = first.item; first = first.next; n--; return item; } public Item top() { return first.item; } @Override public Iterator<Item> iterator() { return new ReverseArrayIterator(); } private class ReverseArrayIterator implements Iterator<Item> { private Node p = first; @Override public boolean hasNext() { return p != null; } @Override public Item next() { Item item = p.item; p = p.next; return item; } } public static void main(String[] args) { Stack<String> s; s = new Stack<String>(); while (!StdIn.isEmpty()) { String item = StdIn.readString(); if (!item.equals("-")) s.push(item); else if (!s.isEmpty()) StdOut.print(s.pop() + " "); } StdOut.println("(" + s.size() + " left on stack)"); } }
测试用例:
/** * Description : * Author : mn@furzoom.com * Date : Sep 28, 2016 2:25:18 PM * Copyright (c) 2013-2016, http://furzoom.com All Rights Reserved. */ package com.furzoom.lab.algs.ch103; import edu.princeton.cs.algs4.StdIn; /** * ClassName : E10303 <br> * Function : TODO ADD FUNCTION. <br> * date : Sep 28, 2016 2:25:18 PM <br> * * @version */ public class E10303 { public static boolean isValid(int[] seq) { Stack<Integer> stack = new Stack<Integer>(); int currentNum = 9; int index = 9; while (currentNum >= 0) { if (index >= 0 && seq[index] == currentNum) { index--; currentNum--; } else if (!stack.isEmpty() && stack.top() == currentNum) { stack.pop(); currentNum--; } else { if (index < 0) break; stack.push(seq[index]); index--; } } return stack.isEmpty(); } public static void main(String[] args) { while (!StdIn.isEmpty()) { String line = StdIn.readLine(); String[] values = line.split("\s+"); int[] nums = new int[10]; for (int i = 0; i < values.length; i++) { nums[i] = Integer.parseInt(values[i]); } if (isValid(nums)) { System.out.println("OK"); } else { System.out.println("No"); } } } }
结果如下 :
>java -cp ".;../lib/algs4.jar" com .furzoom.lab.algs.ch103.E10303 < com/furzoom/lab/algs/ch103/E10303.txt OK No OK OK OK No No OK
测试数据文件 E10303.txt为:
4 3 2 1 0 9 8 7 6 5 4 6 8 7 5 3 2 9 0 1 2 5 6 7 4 8 9 3 1 0 4 3 2 1 0 5 6 7 8 9 1 2 3 4 5 6 9 8 7 0 0 4 6 5 3 8 1 7 2 9 1 4 7 9 8 6 5 3 0 2 2 1 4 3 6 5 8 7 9 0