题目:
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.
思路:
思路1是用NP的方式来罗列出所有的排列再找出第k个结果,这种方法的时间复杂度与空间复杂度比较高。思路2是研究排序结果的规律,例如取n是,结果可以分为n个组,第一组是第一个数字取最小的那个(即1),第k组是取数字排第k小的那个(即k),每组的数字个数是(n-1)!。依次类推可以递归到n为1时。最终k可以表示为k=A1(n-1)!+A2(n-2)!+…+An,其中Ak代表该数为剩余数字中第Ak小的数字。 例如,n=3,k=5时,我们首先将k换算成4(第一个元素为0而不是1),由于(n-1)!=2,所以第一个元素应该是第4/2=2小的元素。第二个元素的k=4%2=0,且(n-1)!=1,所以第二个元素应该是第0小的元素。第三个元素的k=0%1=0,且(n-1)!=1,所以第三个元素应该是第0小元素。一开始的数字为(1,2,3)第一位是第2(0表示第一位)小元素,故取3,第二位是剩余数字(1,2)中第0小的元素,即为1,第三位是剩余数字(2)中第0小的元素,即2。所以结果为312。
代码:
思路1:
class Solution {
public:
string result;
int count;
string str;
vector<bool> num;
string getPermutation(int n, int k) {
for(int i =0;i<n;i++)
{
num.push_back(false);
}
for(int i =0;i<n;i++)
{
str.push_back('.');
}
count = 0;
permutation(n,0,k);
return result;
}
void permutation(int n,int k,int c)
{
if(k==n)
{
if(count==c-1)
{
result = str;
}
else
{
count++;
}
}
else
{
for(int i =0;i<n;i++)
{
if(!num[i])
{
str[k] = i+'1';
num[i]=true;
permutation(n,k+1,c);
str[k] = '.';
num[i]=false;
}
}
}
}
};
思路2:
class Solution {
public:
string getPermutation(int n, int k) {
int base=1;
for(int i=2;i<n;i++)
{
base *= i;
}
int* A = new int[n];
int sum = k-1;
for(int i=0;i<n;i++)
{
A[i] = sum/base;
sum = sum%base;
if(base!=1)
base/=(n-1-i);
}
bool* num = new bool[n];
for(int i=0;i<n;i++)
{
num[i] = false;
}
string str;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(!num[j])
{
if(A[i]==0)
{
str.push_back(j+'1');
num[j] = true;
break;
}
else
{
A[i]--;
}
}
}
}
return str;
}
};
另一种写法
class Solution {
public:
bool * occupied;
int len;
string getPermutation(int n, int k) {
initializeOccupiedArray(n);
return generatePermutation(n, k);
}
string generatePermutation(int n, int k){
string result;
if(n == 1){
result.push_back(getNumber(1));
}
else{
int base = getBase(n-1);
result.push_back(getNumber(((k-1) / base) + 1));
result += generatePermutation(n - 1, ((k-1) % base) + 1);
}
return result;
}
void initializeOccupiedArray(int n){
occupied = new bool[n];
len = n;
for(int i = 0; i < n; i++){
occupied[i] = false;
}
}
int getBase(int k){
int base = 1;
for(int i = 1; i <= k; i++){
base *= i;
}
return base;
}
char getNumber(int k){
for(int i = 0; i < len; i++){
if(!occupied[i]){
k--;
}
if(k == 0){
occupied[i] = true;
return i + 1 + '0';
}
}
}
};