任何人都可以解释算法,以便在仅使用单个堆栈时生成可能的排列,并且push和pop是唯一允许的操作。 已经搜索了很多,但没有明确的答案。 此类排列的总数也由加泰罗尼亚数字给出。但我没有得到证据。如果可能的话,请解释一下。
谢谢!
答案 0 :(得分:5)
此问题使用输入队列和输出队列以及堆栈。
操作是“将项目从输入队列推送到堆栈”和“将项目从堆栈弹出到输出队列”。
1 2 3
output ______ ______ input
\ /
<--+ | +---
pop | | | push
| | v
stack
例如,使用输入1 2 3
,您可以按以下顺序获取输出2 1 3
:
但是如果你尝试生成3 1 2
,那么你会很难。
如何生成这些操作可能产生的所有排列?好吧,递归执行是微不足道的:在任何给定状态(“状态”由输入队列,堆栈和输出队列的内容组成)中,最多可以执行两种可能的操作(可以推送)如果输入队列中至少有一个项目;如果堆栈中至少有一个项目,则可以弹出),这将为您提供最多两个可供探索的新状态。
关于这个问题以及与加泰罗尼亚语数字的关系的进一步细节,去找一份Knuth的“计算机程序设计的艺术”,第1卷(第3版) - 它在§2.2.1中讨论过;请参阅第242-243页的练习2 - 5(以及第240页的更好的图表版本!)。
答案 1 :(得分:0)
首先,在以下假设下,不可能为任意排列编写算法来执行此操作:
您只能按顺序读取输入内容。
类似地顺序写入输出,写入输出的数据一旦写入就无法读取。
除了一个堆栈,您只能获得恒定的内存量。 (这意味着没有额外的递归或数据结构)。
这是无上下文语言的泵浦引理的结果:
维基:http://en.wikipedia.org/wiki/Pumping_lemma_for_context-free_languages
(或者还要检查:Michael Sipser(1997)。计算理论导论。我相信这是第4章的练习之一。)
现在,您可以轻松实现一种算法,通过破坏这些假设中的任何一个来解决此问题。例如,如果您可以任意读取输入,那么您不需要堆栈:
def permute(seq, permutation):
result = []
for i in permutation:
result.push(seq[i])
return result
或者,如果你修复了一个排列,问题变得有限,你同样不需要堆栈。您只需将通常的算法展开到所有输入的特殊情况(即就像在编译器中进行部分评估一样)。这非常可怕,所以我不打算写出所有的细节,但它仍然有效,因为可能的输入总数是固定的(但很大!)常数。
答案 2 :(得分:0)
我正在考虑同样的问题并最终编写了一个小的Prolog程序来生成排列,并“发现”与加泰罗尼亚数字的关系,然后找到了你的问题。所以这不是你问题的真正答案,但这里是Prolog程序:
% Generate permutation counts
count_pushpop(N-K) :-
length(_, N),
findall(Seq, pushpop(N, Seq), Seqs),
length(Seqs, K).
% Create an integer sequence from 1 to N
% and permutate it using all possible push-pop
% operations starting with an empty stack.
pushpop(N, Seq) :-
numlist(1, N, List),
pushpop(List, [], Seq).
% Generate all the possible ways a list
% of items can be pushed into a stack
% and poped out of it.
pushpop([], [], []).
pushpop([H | List], Stack, Seq) :-
pushpop(List, [H | Stack], Seq).
pushpop(List, [H | Stack], [H | Seq]) :-
pushpop(List, Stack, Seq).
证明并非所有n!
排列都是可能的:
?- findall(Seq, pushpop(3, Seq), Seqs).
Seqs = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [1, 3, 2], [1, 2, 3]].
证明它会生成加泰罗尼亚语数字(如果不是堆栈溢出,则将作为证据;)):
?- count_pushpop(N-K).
N = K, K = 0 ;
N = K, K = 1 ;
N = K, K = 2 ;
N = 3,
K = 5 ;
N = 4,
K = 14 ;
N = 5,
K = 42 ;
N = 6,
K = 132 ;
N = 7,
K = 429 ;
N = 8,
K = 1430 ;
N = 9,
K = 4862 ;
N = 10,
K = 16796 ;
N = 11,
K = 58786 ;
N = 12,
K = 208012 ;
ERROR: Out of global stack