A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:
012 021 102 120 201 210
What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
对 0123456789 作全变换,按由小到大排列,第1000,000个数是那个?
我们先来看看数字少的情况。
就拿上面的012来说吧
我们赋予每一位一个权值
0 1 2
2! 1! 0
我们交换0和1,然后对后两位由小到大排序,102是第3小排列,比第1小排列增加了2!
交换0和2,然后对后两位由小到大排序,201位于第5小排列,比第1位增加了2!×2
我们来看看第6小排列,比第一小排列增加了5
而 5 = 2×2! + 1×1!
我们先把第1个与位于它后面2位的数字交换,变为 210,然后把第一位数字之后的数字排序 变为 201,这样就增加了4
然后把第第二位与位于它后面1位的数字交换,变为201,再把第二位数字后面的数字排序,变为210,这样就增加了5,既第6小排列
我们再来看看四个数字的
0 1 2 3
3! 2! 1! 0
我们来找第23个排列,要比第1个排列大22
22 = 3×3! + 2×2!
按照上面的思路
先把第一位和它后面3位的数字交换,变为 3120, 然后把第一位之后的数排序 为 3012 这样就增加了 3×3!
再把第二位和它后面2位的数字交换,再排序,变为 3201,就是最后结果了
所以我们要找0123456789的1000,000位也可以按照这样的思路,增加999,999就是
0 1 2 3 4 5 6 7 8 9
9! 8! 7! 6! 5! 4! 3! 2! 1! 0
2 6 6 2 5 1 2 1 1
第3排就是该位和它要交换的位差的位数
我们用编程来看看这一过程
#include < vector >
#include < algorithm >
using namespace std;
int main(){
int factorial[ 9 ];
int sign[ 9 ];
int mul = 1 ;
int sum = 999999 ;
int tmp;
vector < int > out ;
for ( int i = 0 ; i < 10 ; i ++ ){
out .push_back(i);
}
for ( int i = 1 ; i < 10 ; i ++ ){
mul = mul * i;
factorial[ 9 - i] = mul;
}
for ( int i = 0 ; i < 9 ; i ++ ){
sign[i] = sum / factorial[i];
sum -= sign[i] * factorial[i];
}
for ( int i = 0 ; i < 9 ; i ++ ){
cout << i << ' \t ' << sign[i] << ' \t ' << factorial[i] << endl;
}
cout << endl;
for ( int i = 0 ; i < 9 ; i ++ ){
tmp = out [i];
out [i] = out [sign[i] + i];
out [sign[i] + i] = tmp;
sort( out .begin() + i + 1 , out .end());
for ( int j = 0 ; j < 10 ; j ++ ){
cout << out [j];
}
cout << endl;
}
return 0 ;
}
前面横着的是我们得到的那张表。中间是要交换的位数,后面是权值。
由于最后一位9对应的权值和要移的位数始终为0,所以没有列出
下面是每次调整排序后的结果
最后一行就是最后的结果