题目:
给出集合 [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"
示例 2:
输入: n = 4, k = 9 输出: "2314"
分析:
给定1-n的全排列,问你第k个排列为多少?
我们可以一位一位的确定,首先看第一位,以同一个数字开头的排列肯定有(n-1)!种,
依据这个,我们可以确认第一位应该是1-n中的第几个数字,k/(n-1)! 表示第k个序列经过多少个1-n中的数字,即是第一位在数组中的第几个数字(0——n-1),用过这个数字后,标记上,注意:当k%(n-1)! == 0时,表示刚刚是以此位开头的序列中的最后一个序列。此时它经过的1-n中的数字应该-1.
然后考察第二位,此时k%(n-2),就相当于k,做法跟第一位时一样,这样直到最后一位
代码:
class Solution {
public:
int mul(int n){
int res=1;
for(int i=n;i>=1;i--){
res *= i;
}
return res;
}
char num[9]={'1','2','3','4','5','6','7','8','9'};
bool vis[9];
char get(int n,int cnt){
int pos=0;
for(int i=0;i<n;i++){
if(vis[i]) continue;
cnt--;
if(cnt==0){
pos=i;
break;
}
}
vis[pos]=true;
return num[pos];
}
string getPermutation(int n, int k) {
memset(vis,false,sizeof(vis));
string str="";
int cnt=0;
int m=1;
int t=k;
while(cnt<n){
int tmp = mul(n-m);
//cout << tmp << endl;
int pos = t/tmp;
int next = t%tmp;
if(next!=0) pos++;
if(next==0 && pos!=0){
next=tmp;
}
//cout << "pos: " << pos << "next: "<< next<<endl;
str += get(n,pos);
//cout << str << endl;
m++;
cnt++;
t=next;
}
return str;
}
};