给出集合 [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"
思路:这道题的第一想法就是在之前那道题的基础上添加一个计数器Permutation,如果当前计数器等于k那么返回,但是发现我真是simple,之前的通过固定某一个数,然后全排列后面的所有数的方法出来的并不是顺序的。所以要换种方法。
参考这篇帖子:https://www.cnblogs.com/grandyang/p/4358678.html
这道题的解法是找规律,以输入[1,2,3,4]为例:
所有情况按照顺序是:
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412 <--- k = 17
3421
4123
4132
4213
4231
4312
4321
第一个数有6种情况(3!),如果固定了第一个数,第二个数有2种情况(2!),如果固定了第一二个数,第三个数有1种情况(1!),固定了前3个,第四个数有1种情况(0!)。那么怎么第几位数应该是多少呢?以n=4,k=17来举例子:
k=17相当于下标16(以后都是以下标0开始算),由于第0位数有6种情况,所以16/6=2,所以第0位数是1,2,3,4的第2位即3,那么剩下16%6=4位,第1位数有2种情况,所以4/2=2,所以第1位数是1,2,4中的4,这时剩下4%2=0,第2位0/1=0,所以第2位是1,2中的1,剩下0%1=0,第3位0/1=0,所以第3位是剩下的2的2,所以最后的数字是3,4,1,2
所以规律是:
a0=k/(n-1)!
k=k%(n-1)!
a1=k/(n-2)!
k=k%(n-2)!
......
参考代码:
class Solution {
public:
string getPermutation(int n, int k) {
string res;
vector<int> f(n, 1);
for (int i = 1; i < n; i++) f[i] = f[i - 1] * i;
k--;
string num = "123456789";
for (int i = n; i >= 1; i--) {
int j = k / f[i - 1];
k %= f[i - 1];
res.push_back(num[j]);
num.erase(j, 1);
}
return res;
}
};