题目描述
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。
示例 1:
输入:n = 3, k = 3
输出:“213”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
C++
一看就类似 leetcode 46题 全排列,我就用回溯,然后完美超时,,,超时代码:
class Solution {
public:
/*
回溯:因为这是一个全排列的树,没有重复元素,并且选择策略非常明显,
*/
vector<string> res;
string getPermutation(int n, int k) {
string track; //路径
traverse(track,n);
return res[k-1];
}
void traverse(string &track,int n){
//结束条件
if(track.size()==n){
res.push_back(track);
return;
}
for(int i=1;i<=n;i++){
char c=i+'0';
if(find(track.begin(),track.end(),c)!=track.end())
continue; //已经选过的,就不选
//选择
track.push_back(c);
traverse(track,n);
track.pop_back(); //回溯
}
}
};
优化…
估计要要用到数学知识…
class Solution {
public:
/*
优化。。。
数学知识。。
先找第K个排列的首位:
index=K/(n-1)!
K%(n-1)! ==0, 开头第一位是 index
!=0, 开头第一位是inde=index+1
找第二位,K=k-index*(n-1)!
同上。。。
*/
string getPermutation(int n, int k) {
string res;
vector<int> candidates; //候选数字
//求1-n的阶乘
vector<int> factorial(n+1);
factorial[0]=1;
int fact=1;
for(int i=1;i<=n;i++){
candidates.push_back(i);
fact*=i;
factorial[i]=fact;
}
k-=1;
for(int i=n-1;i>=0;i--){
//计算候选数字的index
int index=k/factorial[i];
k-=index*factorial[i];
res.push_back(candidates[index]+'0');
candidates.erase(candidates.begin()+index);
}
return res;
}
};