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.
方案一:
可以一个一个去求解,利用DFS,来找。不过会超时
class Solution {
private:
int a[10];
bool canUse[10];
string ret;
public:
void dfs(int dep, int maxDep, int &k)
{
if (k == 0)
return;
if (dep == maxDep)
{
k--;
if (k == 0)
{
ret = "";
for(int i = 0; i < maxDep; i++)
ret += (char)(a[i] + '0');
return;
}
}
for(int i = 1; i <= maxDep; i++)
if (canUse[i])
{
canUse[i] = false;
a[dep] = i;
dfs(dep + 1, maxDep, k);
canUse[i] = true;
}
}
string getPermutation(int n, int k) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
memset(canUse, true, sizeof(canUse));
dfs(0, n, k);
return ret;
}
};
方案二:
利用数学的方法,比如题目中找到第5个数,其实就是5/(2!),让1和3交换,然后递归一位再找第5%(2!)个数。
但有个小问题,当k%(j!)为0的时候,就要交换后,将剩余的数据翻转。知道了这些,就能写出代码,不过有些繁琐
class Solution {
public:
string getPermutation(int n, int k) {
string str;
int arr[9] = {1,2,3,4,5,6,7,8,9};
if(n<=0 || k<=0)
return str;
int fact = NFact(n);
if(k>fact)
k = k%fact;
fact = fact/n;
int tmp = n-1; //表示要除数
int index = 0; //指示在index位调整
while(k){
while(k<fact){ //跳过不用更改的位置
fact = fact / tmp;
tmp--;
index++;
}
if(k%fact == 0){ //当k%fact == 0与不等于0,执行的情况不一样,分开考虑
int i = k/fact-1;
Swap(arr,index,index+i);
Ajust(arr,index+1,n-1);
break;
}else{
int i = k/fact;
Swap(arr,index,index+i);
k = k%fact;
}
}
for(int i = 0;i < n;i++)
str.push_back(arr[i]+'0');
return str;
}
//求总的个数
int NFact(int n){
if(n==0)
return 1;
return n*NFact(n-1);
}
//调整,将end的元素移动到begin处,并且begin...end-1平移
void Swap(int arr[],int begin,int end){
int temp = arr[end];
for(int i = end;i > begin;i--){
arr[i] = arr[i-1];
}
arr[begin] = temp;
}
//当k%fact==0的时候,调整过以后,后面的数翻转
void Ajust(int arr[],int begin,int end){
while(begin < end){
int temp = arr[begin];
arr[begin] = arr[end];
arr[end] = temp;
begin++;
end--;
}
}
};
方案三:
在n!个排列中,第一位的元素总是(n-1)!一组出现的,也就说如果p = k / (n-1)!,那么排列的最开始一个元素一定是nums[p]。
假设有n个元素,第K个permutation是
a1, a2, a3, ….. …, an
那么a1是哪一个数字呢?
那么这里,我们把a1去掉,那么剩下的permutation为
a2, a3, …. …. an, 共计n-1个元素。 n-1个元素共有(n-1)!组排列,那么这里就可以知道
设变量K1 = K
a1 = K1 / (n-1)!
同理,a2的值可以推导为
a2 = K2 / (n-2)!
K2 = K1 % (n-1)!
…….
a(n-1) = K(n-1) / 1!
K(n-1) = K(n-2) /2!
an = K(n-1)
string getPermutation(int n, int k) {
vector<int> nums(n);
int pCount = 1;
for(int i = 0 ; i < n; ++i) {
nums[i] = i + 1;
pCount *= (i + 1);
}
k--;
string res = "";
for(int i = 0 ; i < n; i++) {
pCount = pCount/(n-i);
int selected = k / pCount;
res += ('0' + nums[selected]);
for(int j = selected; j < n-i-1; j++)
nums[j] = nums[j+1];
k = k % pCount;
}
return res;
}