任何n个字符集的排列都可以与1-n的n个数字的排列一一对应,n个数字的全体排列之间存在一个确定的线性顺序关系。
1.字典序法
设P是1~n的一个全排列:
P = p1p2......pn =p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max{i|pi<pi+1}
2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)
3)对换pi,pk
4)再将pj+1......pk-1pkpk+1...pn倒转得到排列p'=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列P的下一个下一个排列。
例如12345这五个数的数组,字典序法的第一个排列是12345,最后一个是54321
方法如下:
1.从右往左,找到第一个比前一个数小的数a[i],(比如12345,这个数就是a[i]=4。)
2.从右往左,找到第一个a[i](4)小的数a[j](应该是5)。
3.交换a[i]、a[j]。变成12354
4.将a[i]后的数逆序,此例中 4 后面就一个 5 ,逆序仍然是5.结果就是 12354
为方便理解,以上步骤再进行一步。
1.从右向左找到第一个比右边前一个数小的数 3
2.从右往左找到第一个比 3 大的数 4;
3.交换3和4,变成 12453
4. 4(交换前的3的位置) 后的数 53逆序得 12435.就是结果。
1.1计算给定排列的序号
全排列的序号即先于此排列的排列的个数。将先于此排列的排列按前缀分类。
839647521
前缀先于8的排列的个数:7×8!
1********,2********,…,7********
第一位是8,先于83的排列的个数:2×7!
82*******,81*******
前2位是83,先于839的排列的个数:6×6!
831******,832******,834******,835******,836******,837******
前3位是839,先于8396得的排列的个数:4×5!
前4位是8396,先于83964得的排列的个数:2×4!
前5位是83964,先于839647得的排列的个数:3×3!
前6位是839647,先于8396475得的排列的个数:2×2!
前7位是8396475,先于83964752得的排列的个数:1×1!
7×8! + 2×7! + 6×6!+ 4×5! + 2×4! + 3×3! + 2×2! + 1×1! = 297191
即839647521的序号是 297191,表明839647521前面有297191个排列
将8!,7!,…,1!前面的系数抽出,放在一起得到 72642321
72642321是计算排列839647521的序号的中间环节,称之为中介数。
中介数,序号和排列之间是一一对应的关系。
1.2从序号得到排列
需要利用中介数,来构造排列。
中介数的特点:记录当前数字右边比当前数字小的数字的个数,例如对上面的排列,中介数为72642321
前2位是83,左边前缀用掉了8,3,因此右边比9小的数字是8-2=6个
中介数记录了排列中每位数字的排列结构,因此可以用来构造对应的排列。
[例] 由72642321推算出839647521
方法1
P1 P2 P3 P4 P5 P6 P7 P8 P9
__ __ __ __ __ __ __ __ __
8 3 9 6 4 7 5 2 1
7+1=8 à P1 = 8
2+1=3 à P2 = 3
6+1=7,但3小于7已在P3左边出现,7+1=8,但8已在P3左边出现,8+1=9 à P3=9
4+1=5,但3已经在P4左边出现,5+1=6 →P4=6
2+1=3,但3已经在P5左边出现,3+1=4 →P5=4
3+1=4,但3,4已经在P6左边出现,4+1+1=6,但6已经在P6左边出现, 6+1=7→ P6=7
2+1=3,但3已经在P7左边出现,3+1=4,但4已经在P7左边出现, 4+1=5 → P7=5
1+1=2 → P8=2
→ P9=1