假设某个用例程序会进行一系列入栈和出栈操作。入栈操作会将整数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