输出n的全排列的字典序编号为k的全排列

n个元素{1,2,•••,n}有n!个不同的排列。将这n!个排列按字典序排列。并编号为0,1,2.....,n!-1。每 个排列的编号为其字典序的值。例如。当n=3时,其字典排序为:123,132,213,232,312,321,这六个数的字典序值分别为 0,1,2,3,4,5,现给定任意n,输出字典序为k的排列(0<=k<=n!-1)。

这题 也是来源于今年的美团面试题..

一开始 我也无从下手..

后来 看了http://www.cnblogs.com/submarine/archive/2010/04/12/1941268.html

这边 关于 编号的定义 就差不多明白了


2 6 4 5 8 1 7 3

看例子:

tot=0;

比2小的数有1个,则 tot+=1*7!;

比6小的数有4个,则 tot+=4*6!;

比4小的数有2个,则 tot+=2*5!;

比5小的数有2个,则 tot+=2*4!;

比8小的数有3个,则 tot+=3*3!;

比1小的数有0个,则 tot+=0*2!;

比7小的数有1个,则 tot+=1*1!;

比3小的数没有;

(注:在排列中,求比某个数小的数的个数时,排除之前出现过的数)

 

这是来源于他的博客 介绍  明白了就好

下面是我的代码  自己测试的几组数据都已通过.

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 const int size = 1010;
 6 typedef long long LL;
 7 LL fact[size];
 8 bool vis[size];
 9 void init( )
10 {
11     fact[0] = 1;
12     for( int i = 1 ; i<size ; i++ )
13     {
14         fact[i] = fact[i-1] * i;
15     }
16 }
17 
18 int main()
19 {
20     LL n , k , t , mmin , cnt , temp;
21     init( );
22     while( cin >> n >> k )
23     {
24         mmin = 1;
25         memset( vis , false , sizeof(vis) );
26         for( int i = 1 ; i<=n ; i++ )
27         {
28             if( k==0 )
29             {
30                 for( int j = mmin ; j<=n ; j++ )
31                 {
32                     if( !vis[j] )
33                     {
34                         cout << j << " ";
35                     }
36                 }
37                 break;
38             }
39             else if( k<fact[n-i] )
40             {
41                 while(1)
42                 {
43                     if( !vis[mmin] )
44                     {
45                         vis[mmin] = true;
46                         cout << mmin << " ";
47                         break;
48                     }
49                     ++mmin;
50                 }
51             }
52             else
53             {
54                 cnt = 0;
55                 t = k / fact[n-i];
56                 k -= t * fact[n-i];
57                 temp = mmin;
58                 ++ t;
59                 while(1)
60                 {
61                     if( !vis[temp] )
62                     {
63                         ++ cnt;
64                     }
65                     if( cnt == t )
66                     {
67                         vis[temp] = true;
68                         cout << temp << " ";
69                         break;
70                     }
71                     ++ temp;
72                 }
73             }
74         }
75         cout << endl;
76     }
77     return 0;
78 }
View Code


先折叠起来 大家可以写完后 和我 对拍下

today:

  从吹牛b到懂得沉默 就开始慢慢成熟了

 

 

 

 

 

 

just follow your heart
原文地址:https://www.cnblogs.com/radical/p/3986784.html