您的位置:首页 > 编程语言 > C语言/C++

LeetCode(60): Permutation Sequence (C++)

2015-12-01 10:44 525 查看

一、题目

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.

二、分析

    此题可用暴力枚举,即调用 k - 1 次的 std::next_permutation() 或者是在 LeetCode(31): Next Permutation
所实现的函数,但这样做求出了前 k  个所有排列,会超时,我们只需要求出第 k 个即可。

    为了能更清楚地说明接下来的算法,我们先来看对于 n = 3 时,所有排列的特点。



可分为 n = 3 组,每组有 (n - 1)! 即 (3 - 1)! 个排列;

第 m 组(其中, 1 ≤ m ≤ n)中,第一个数为所有数字升序排列的第 m 个数,如:第 3 组第一个数为 [1, 2, 3] 的第三个数,即3;

第 m 组的第一个排列,即总的第 (m - 1) * (n - 1)! + 1 个排列,第一个数之后,为升序排列;
第 m 组的最后一个排列,即总的第 m * (n - 1)! 个排列,第一个数之后,为降序排列;
    有此规律,我们便可递归求解,即总的 n 个数的第 k 个排列,可以通过确定第一个数之后,求剩下的 (n - 1) 个数的第 k - m * (n - 1)! 个排列,其中,m = floor(k / (n - 1)!)。


三、代码实现

class Solution {
private:
long fact(int n){
if(n == 0){
return 1;
}else{
return n * fact(n - 1);
}
}

void permute(string& str, int start, int k){
if(k == 1 || k == 0){
return;
}

const int len = str.size();

if(k == fact(len - start)){
sort(str.begin() + start, str.end(), greater<char>());
return;
}else{
int tmp = fact(len - start - 1);
int num = k / tmp;

k -= num * tmp;

if(k == 0){
swap(str[start], str[start + num - 1]);
sort(str.begin() + start + 1, str.end(), greater<char>());
}else{
swap(str[start], str[start + num]);
sort(str.begin() + start + 1, str.end());
}

permute(str, start + 1, k);
}

}

public:
string getPermutation(int n, int k) {
string s;
int sum = 0;

s.resize(n);
for_each(s.begin(), s.end(), [&sum](char& c){ c = '0' + (++sum); });

permute(s, 0, k);

return s;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息