问题链接:
https://leetcode-cn.com/problems/permutation-sequence/
部分参考于:
https://leetcode-cn.com/problems/permutation-sequence/solution/di-kge-pai-lie-by-leetcode-solution/
算法
数学
注意到问题规模,如果将全排列全部列出,那么时间复杂度将为O(n!),那么最好是直接确定第k个排列。
由于排列的顺序是字典序排列的,那么根据k的范围就可以确定第一个数字的大小。即等于(k-1)/(n-1)!+1,此处为整数除法。
递归
可以转化为,先确定第一个数字,然后确定剩余排列的第一个元素,以此递归。
函数
string to_string(int val) ,仍旧是简单将int转化为string的函数。
实现
class Solution {
public:
string getPermutation(int n,int k) {
vector<int> factorial(n);
factorial[0] = 1;
for (int i = 1; i < n; ++i) {
factorial[i] = factorial[i - 1] * i;//计算阶乘
}
--k;
string ans;
vector<int> valid(n + 1, 1);//状态数组
for (int i = 1; i <= n; ++i) {
int order = k / factorial[n - i] + 1;//向下取整
for (int j = 1; j <= n; ++j) {
order -= valid[j];//逼近下一个排列的开头,若为0则代表是已经使用过的,则order直接+0无影响order的值跳过
if (!order) {
//此时order恰好找到开头的数字
ans +=to_string(j);//string扩展
valid[j] = 0;//标记为已经使用的数字
break;//本轮查找结束,跳出循环,进入下一层
}
}
k %= factorial[n - i];//k取得余数
}
return ans;
}
};