小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
给出集合 [1,2,3,...,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123""132""213""231""312""321"
给定 n 和 k,返回第 k 个排列。
示例 1:
**输入:**n = 3, k = 3 输出:"213"
示例 2:
**输入:**n = 4, k = 9 输出:"2314"
示例 3:
**输入:**n = 3, k = 1 输出:"123"
提示:
1 <= n <= 91 <= k <= n!
解题思路
一个简单明了的解题方法。
找规律:位数单个数的可能性总数为(n-位数)!,
例如,有n=4,第一位数字为1的全部可能性就是3!,如果k>3!,自然,第一位数字是1以外的数。
设置一个位置符count,在数字符数组中,当k>位数可能数,count加一。
当小于或等于,输出当前位置符对应的数,count重置为0,继续下一个位数。
直到答案输出。
可能我表述的不太好,所以我画了张图方便理解。
代码
/**
* @param {number} n
* @param {number} k
* @return {string}
*/
var getPermutation = function(n, k) {
let num = []; // ['1','2','3','4']
let fa = [];
let tmp = 1;
for(let i=1;i<=n;i++){
num.push(String(i)); // 数字符集合
tmp *= i;
fa.push(tmp); // 阶乘集合
}
fa.pop(); // 最后一个是总数,没有作用所以推出它
let count = 0; // 当前选中字符位置
let res = '';
while(fa.length>0){
let sub = fa.length-1;
if(k>fa[sub]) { // 大于就减去并位置+1
k = k - fa[sub];
count++;
}else{ // 小于等于就输出到字符串,重置字符位置
res += num.splice(count,1)[0];
count = 0;
fa.pop();
}
}
return res + num[0] // 遍历完还剩一个在数组中,加上
};
最后
曾梦想仗剑走天涯
看一看世界的繁华
年少的心总有些轻狂
终究不过是个普通人
无怨无悔我走我路