第k个排序
题目描述
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。
说明:
给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。
样例
- 输入: n = 3, k = 3
输出: “213” - 输入: n = 4, k = 9
输出: “2314”
Code1
使用next_permutation();
string getPermutation(int n, int k) {
string s(n, '0');
for(int i=0; i<n; ++i) {
s[i]+=i+1;
}
for(int i=0; i<k-1; ++i) {
next_permutation(s.begin(), s.end());
}
return s;
}
template<typename BidiIt>
bool next_permutation(BidiIt first, BidiIt last) {
const auto rfirst = reverse_iterator<BidiIt>(last);
const auto rlast = reverse_iterator<BidiIt>(first);
auto pivot=next(rfirst);
while(pivot !=rlast && *pivot >= *prev(pivot)) {
++pivot;
}
if(pivot ==rlast) {
reverse(rfirst, rlast);
return false;
}
auto change=find_if(rfirst, pivot, bind1st(less<int>(), *pivot));
swap(*change, *pivot);
reverse(rfirst, pivot);
return true;
}
Code2
康托编码,时间复杂度O(n),空间复杂度O(1);
string getPermutation(int n, int k) {
string s(n, '0');
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;
}
template<typename Sequence>
Sequence kth_permutation(const Sequence &seq, int k) {
const int n=seq.size();
Sequence S(seq);
Sequence result;
int base=factorial(n-1);
--k;
for(int i=n-1; i>0; k%=base,base/=i,--i) {
auto a=next(S.begin(), k/base);
result.push_back(*a);
S.erase(a);
}
result.push_back(S[0]);
return result;
}
若有疑问可评论交流=_=!