• 输出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
  • 相关阅读:
    单例模式中的懒汉式以及线程安全性问题
    单例模式中的饿汉模式
    自我管理的8个好习惯
    从java字节码角度看线程安全性问题
    工作上的建议
    从线程的优先级看饥饿问题
    多线程存在哪些风险
    DirectX SDK (June 2010)安装错误S1023,解决方法
    Microsoft DirectX SDK 2010 版本下载
    如果程序集是从 Web 上下载的,即使它存储于本地计算机,Windows 也会将其标记为 Web 文件,http://go.microsoft.com/fwlink/?LinkId=179545
  • 原文地址:https://www.cnblogs.com/radical/p/3986784.html
Copyright © 2020-2023  润新知