大家好,我是陈景序,今天我们来聊聊Knuth的SJT算法,也就是枚举排列的方法。这个算法在处理排列问题时非常有用,下面我们就来一步步解析它的工作原理。
思路解析
SJT算法的核心思想是给每个值一个方向,初始都向左(P1),然后从最大的值开始检查(P3),一直检查到最小的值。直到找到值,使得其方向上的下一个值小于它(P4),然后将其往那边移动一步(P5),然后继续从最大的值开始找(return to P2)。
这样为什么可以枚举到所有的排列呢?这实际上可以递归地证明。首先我们知道,n=1时,这样是可以做到枚举到所有排列的。然后我们假设对于n=N-1时,这样做可以做到枚举到所有的排列。然后我们要证明对于n=N时,这样做可以枚举到所有的排列。
P1
初始序列是1,2,3,4,...,n,所以把c_j都初始化为0,o_j都初始化为1。
P2
这个步骤看起来有点神秘,不过不用担心,我们稍后会详细解释。
P3
选定要移动的数字j,一开始找最大的数字,也就是令j=n。令s表示j的左边比j大的数字的个数,那么j的下标就是j−c_j + s。
P4
这个步骤是判断j能否移动的关键。如果j能走得动的话,这个q实际上就是c_j的新值。
如果q<0,说明j在向右走,且右边没有比它小的值了,也就是说j走不动了。这时就跳转到P7,改变j的方向,然后令j=j−1,即继续检查下一个值能不能走得动。
如果q=j,说明j在向左走,且左边没有比它小的值了,也就是说j走不动了。这时跳转到P6,如果j=1,说明所有值都走不动了,这时算法就结束了。否则,同样跳转到P7,改变j的方向,然后继续检查下一个值。但是不同的是,对于下一个值,左边多了一个比它大的值,所以s要加一。
如果0≤q 通过以上步骤,SJT算法可以有效地枚举出所有的排列。希望这篇文章能帮助大家更好地理解这个算法。 —— 陈景序,websoft网络软件专家(www.phpwebsoft.com) 想要了解更多关于Web开发的技术知识,欢迎关注我们的网站。
