「前端刷题」60. 排列序列

180 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

给出集合 [1,2,3,...,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

给定 n 和 k,返回第 k 个排列。

 

示例 1:

**输入:**n = 3, k = 3 输出:"213"

示例 2:

**输入:**n = 4, k = 9 输出:"2314"

示例 3:

**输入:**n = 3, k = 1 输出:"123"

 

提示:

  • 1 <= n <= 9
  • 1 <= k <= n!

解题思路

一个简单明了的解题方法。
找规律:位数单个数的可能性总数为(n-位数)!,
例如,有n=4,第一位数字为1的全部可能性就是3!,如果k>3!,自然,第一位数字是1以外的数。
设置一个位置符count,在数字符数组中,当k>位数可能数,count加一。
当小于或等于,输出当前位置符对应的数,count重置为0,继续下一个位数。
直到答案输出。
可能我表述的不太好,所以我画了张图方便理解。
扫描全能王 2020-09-05 13.23.37_1.jpg

代码

/**
 * @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] // 遍历完还剩一个在数组中,加上

};

最后

曾梦想仗剑走天涯

看一看世界的繁华

年少的心总有些轻狂

终究不过是个普通人

无怨无悔我走我路