Permutation Sequence

原创 2015年07月10日 16:46:38

The set [1,2,3,⋯,n] contains a total of n! unique permutations.
By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3):
“123”
“132”
“213”
“231”
“312”
“321”
Given n and k, return the kth permutation sequence.
Note: Given n will be between 1 and 9 inclusive.

中文
给定n个数,求第k个排序。

{1,2,3,4,…,n}表示1,2,3,…,n的排列,如 {1,2,3} 按从小到大排列一共6个:123 132 213 231 312 321,代表数字 1 2 3 4 5 6,也就是把10进制数与一个排列对应起来,他们间的对应关系可由康托展开来找到。简单的说就是求一个排列数在所有排列中是第几小的。
德国数学家康托(应该不会重名吧)发现其实可以又更简单高效的算法来解决这个问题:例如我们求35412在{1,2,3,4,5}的生成的排列中是第几小的:
第一位是3,第一位比3小的排列数肯定小于35412,比3小的有1,2;共2个数,所以有2*4!;
第二位是5,同理,比5小的有1,2,3,4;因为3已经在前面出现了,所有还有3个比5小的,3*3!;
第三位是4,比4小的有1,2,3;3在前面出现了,还有2个比4小的数,2*2!;
第四位是1,没有比1小的数,所以是0*1!;
最后一位无论是几,比它小的数在前面肯定都出现了,所以有0*0!;
所以,比35412小的排列数共有:2*4!+3*3!+2*2!+0*1!+0*0!=70,35412是第71小的数。

class Solution {
public:
    string getPermutation(int n, int k) {
        int total = factorial(n);//获得总阶乘
        //下标k从k-1开始,从0开始,就能与下面候选的字符串对应。0-n-1.当求n!个序列时,得到数字n,这样就不方便得到候选数字了。
        string candidate = string("123456789").substr(0, n);//获得从0开始长度为n的字符串
        string res(n,' ');//初始化字符串
        for(int i = 0; i < n; i++)//依次计算排列的每个位
        {
            total /= (n-i);//第i个数后面的阶乘。
            int index = (k-1) / total;//求得这一位的最前面的数。
            res[i] = candidate[index];//将第i位保持起来。
            candidate.erase(index, 1);//删除掉该数,删除从这个索引开始的1个字符
            k -= index*total;//求得剩余的位数。k-前面数字确定的位数。
        }
        return res;
    }
    int factorial(int n)
    {
        int res = 1;
        for(int i = 2; i <= n; i++)
            res *= i;
        return res;
    }
};

这道题是让求出n个数字的第k个排列组合,由于其特殊性,我们不用将所有的排列组合的情况都求出来,然后返回其第k个,我们可以只求出第k个排列组合即可,那么难点就在于如何知道数字的排列顺序,可参见网友喜刷刷的博客,首先我们要知道当n = 3时,其排列组合共有3! = 6种,当n = 4时,其排列组合共有4! = 24种,我们就以n = 4, k = 17的情况来分析,所有排列组合情况如下:

1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412 <— k = 17
3421
4123
4132
4213
4231
4312
4321

我们可以发现,每一位上1,2,3,4分别都出现了6次,当第一位上的数字确定了,后面三位上每个数字都出现了2次,当第二位也确定了,后面的数字都只出现了1次,当第三位确定了,那么第四位上的数字也只能出现一次,那么下面我们来看k = 17这种情况的每位数字如何确定,由于k = 17是转化为数组下标为16:

最高位可取1,2,3,4中的一个,每个数字出现3!= 6次,所以k = 16的第一位数字的下标为16 / 6 = 2,即3被取出
第二位此时从1,2,4中取一个,k = 16是此时的k’ = 16 % (3!) = 4,而剩下的每个数字出现2!= 2次,所以第二数字的下标为4 / 2 = 2,即4被取出
第三位此时从1,2中去一个,k’ = 4是此时的k” = 4 % (2!) = 0,而剩下的每个数字出现1!= 1次,所以第三个数字的下标为 0 / 1 = 0,即1被取出
第四位是从2中取一个,k” = 0是此时的k”’ = 0 % (1!) = 0,而剩下的每个数字出现0!= 1次,所以第四个数字的下标为0 / 1= 0,即2被取出

那么我们就可以找出规律了
a1 = k / (n - 1)!
k1 = k

a2 = k1 / (n - 2)!
k2 = k1 % (n - 2)!

an-1 = kn-2 / 1!
kn-1 = kn-2 / 1!

an = kn-1 / 0!
kn = kn-1 % 0!

代码如下:
class Solution {
public:
string getPermutation(int n, int k) {
string res;
string num = “123456789”;
vector f(n, 1);
for (int i = 1; i < n; ++i) f[i] = f[i - 1] * i;
–k;
for (int i = n; i >= 1; –i) {
int j = k / f[i - 1];
k %= f[i - 1];
res.push_back(num[j]);
num.erase(j, 1);
}
return res;
}
};

版权声明:本文为博主原创文章,未经博主允许不得转载。

Permutation递归解法

permutation类型题的解法
  • a6219221
  • a6219221
  • 2016年09月07日 03:21
  • 433

排列组合(permutation)系列解题报告

本文讲解4道关于permutation的题目。 1. Permutation:输出permutation——基础递归 2. Permutation Sequence: 输出第k个permutatio...
  • abcjennifer
  • abcjennifer
  • 2014年10月18日 18:46
  • 9127

寻找排列数中的第k个数 Permutation Sequence

问题:The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling al...
  • luckyjoy521
  • luckyjoy521
  • 2014年03月24日 21:11
  • 1790

CF 482A(Diverse Permutation-相邻距离不同数为k的1~n全排列构造)

A. Diverse Permutation time limit per test 1 second memory limit per test 256 megabytes ...
  • nike0good
  • nike0good
  • 2014年10月31日 11:42
  • 1867

总结帖:全排列Permutation,子集subset 递归模板

两个经典递归模板,以前写过,现在再过一遍! 基本思路: 如果题目给的输入时数组,首先先要把数组转为ArrayList,因为ArrayList可以很方便地插入,删除,添加! 其次,递归函数的形式都一...
  • hellobinfeng
  • hellobinfeng
  • 2014年03月06日 05:51
  • 2948

[LeetCode]Permutation全排列和去重全排列

一、问题描述: 借助这道题总结一下全排列问题吧 https://leetcode.com/problems/permutations/ Given a collection of disti...
  • CristianoJason
  • CristianoJason
  • 2016年04月20日 14:02
  • 1974

数据结构基础(3) --Permutation & 插入排序

Permutation(排列组合) 排列问题: 设R = {r1, r2, ... , rn}是要进行排列的n个元素, Ri = R-{ri}; 集合X中元素的全排列记为Permutati...
  • acpchenpeng
  • acpchenpeng
  • 2016年01月28日 15:10
  • 198

Permutation Test 置换检验(转)

Permutation Test 置换检验 显著性检验通常可以告诉我们一个观测值是否是有效的,例如检测两组样本均值差异的假设检验可以告诉我们这两组样本的均值是否相等(或者那个均值更大)。我们在实验中...
  • u011467621
  • u011467621
  • 2015年08月25日 09:18
  • 3662

详解STL中next_permutation()函数实现

前几天,遇到一个可以用穷举法解决的问题,就是中给定几个数子,让凑出等式的类型。之前,我都是用写个函数递归调用,今天突然想到其实有一个更简单的方式来实现穷举,那就是使用STL中的next_permuta...
  • kuaisuzhuceh
  • kuaisuzhuceh
  • 2014年01月18日 17:21
  • 1071

全排列问题算法及实现(Permutation)

前言 做项目遇到数据采集系统中ADC拼合问题,如果顺序不对,波形就是错误的(题外话),为了找到正确的顺序,涉及到排列问题。 什么是排列组合 定义 一般地,从n个不同元素中取出m(m≤n)个...
  • u011391629
  • u011391629
  • 2016年12月19日 21:23
  • 649
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Permutation Sequence
举报原因:
原因补充:

(最多只允许输入30个字)