第k个排列
难度:中等
给出集合 [1,2,3,…,n]
,其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
说明:
示例 1:
输入: n = 3, k = 3
输出: "213"
示例 2:
输入: n = 4, k = 9
输出: "2314"
这里先介绍两个函数及用法:next_permutation和prev_permutation
函数原型:
next_permutation:
1.template< class BidirIt >bool next_permutation( BidirIt first, BidirIt last );
2.template< class BidirIt, class Compare >bool next_permutation( BidirIt first, BidirIt last, Compare comp );
prev_permutation:
1.template< class BidirIt >bool prev_permutation( BidirIt first, BidirIt last);
2.template< class BidirIt, class Compare >bool prev_permutation( BidirIt first, BidirIt last, Compare comp);
first,end ——重新排序的元素范围
comp —— 自定义比较函数(默认字典排序)
顾名思义,next_permutation就是求下一个排列组合,而prev_permutation就是求上一个排列组合。首先我们必须了解什么是“下一个”排列组合,什么是“前一个”排列组合。考虑由三个字符所组成的序列{a,b,c}。
那么按照字典序排升序他们一共有下面这几种排列方式:
如果给定排列方式P,令P为{acb},那么next_permutation即求P+1也就是{bac},prev_permutation也就是求P-1即为{abc}。当然也可以自定义谓词函数进行自定义的“下一个排列组合”。
#include
#include
#include
#include
#include
#include
#include
#include
题目分析:
第K个排列,讲道理是用回溯法全排列,然后确定。这里遇到两个问题:1.全排列一遍会超时;2.会发现常用的全排列还不是字典顺序。所以提供两种思路:1.利用STL中的next_permutation直接求(时间复杂度较高);2.找数学规律
找数学规律:
解题思路:
这道题是让求出n个数字的第k个排列组合,由于其特殊性,我们不用将所有的排列组合的情况都求出来,然后返回其第k个,我们可以只求出第k个排列组合即可,那么难点就在于如何知道数字的排列顺序,可参见https://bangbingsyb.blogspot.com/2014/11/leetcode-permutation-sequence.html
首先我们要知道当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被取出
参考代码:
#include
#include
#include
#include
#include
#include
#include
#include
参考代码(第一种方案):
class Solution {
public:
string getPermutation(int n, int k) {
string str = "123456789";
str = str.substr(0,n);
for (int j = 0; j < k-1; ++j)
{
next_permutation(str.begin(), str.end());
}
return str;
}
};