第k个排列、
描述:
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。
说明:
给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。
示例 1:
输入: n = 3, k = 3
输出: “213”
思路1(下一个排列)
https://blog.csdn.net/amor_1/article/details/104478661
下一个排列的链接在这,对于求第k个排列,可以从初始123…n这个排列开始,求k次下一个排列即可得到第k个排列。
代码可以参考链接。
思路2(康托编码)
利用康托编码的思路,假设有 n 个不重复的元素,第 k 个排列是 a1,a2,a3,…,an,那么 a1 是 哪一个位置呢?
我们把 a1 去掉,那么剩下的排列为 a2,a3,…,an,共计 n−1 个元素,n−1 个元素共有 (n−1)! 个排列,于是就可以知道 a1 = k/(n−1)!。 同理,a2,a3,…,an 的值推导如下:
k2 = k%(n−1)!
a2 = k2/(n−2)!
···
kn−1 = kn−2%2!
an−1 = kn−1/1!
an = 0
对与从左往右每一个ai,ki不断的除和取余。
class Solution {
public:
string getPermutation(int n, int k) {
string s(n,'0');
string result;
for(int i=0;i<n;i++)
{
s[i]+=i+1;
}
return kth_permutation(s,k);
}
private:
int factorial(int n)
{
int result=1;
for(int i=1;i<=n;i++)
{
result*=i;
}
return result;
}
string kth_permutation(string &s,int k)
{
const int n=s.size();
string result;
int base=factorial(n-1);
--k;
for(int i=n-1;i>0;k=k%base,base/=i,--i)
{
auto a =s.begin()+k/base;
result.push_back(*a);
s.erase(a);
}
result.push_back(s[0]);
return result;
}
};