题目描述

给出集合 [1,2,3,…,n] ,其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当n = 3时, 所有排列如下:

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

来源,leetcode 每日一题 第K个排列


给定 n 和 k,返回第 k 个排列。
说明:
给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。
示例 1:

  1. 输入: n = 3, k = 3
  2. 输出: "213"

示例 2:

  1. 输入: n = 4, k = 9
  2. 输出: "2314"

解题思路

  1. 以1-n为首的排列共有 (n-1)!
  2. 通过 k mod (n-1)! 可以确定出一个最开始的范围
  3. 然后在 (n-1) 个数的排列中,继续缩小范围,直到范围不能再小
  4. 至此,排列已经确定

代码

  1. class Solution {
  2. public:
  3. string getPermutation(int n, int k) {
  4. vector<int> factorial(n);
  5. factorial[0] = 1;
  6. // 计算 i个数可能的排列数量
  7. for (int i = 1; i < n; ++i) {
  8. factorial[i] = factorial[i - 1] * i;
  9. }
  10. --k;
  11. string ans;
  12. vector<int> valid(n + 1, 1);
  13. for (int i = 1; i <= n; ++i) {
  14. // 计算第i个数是什么
  15. int order = k / factorial[n - i] + 1;
  16. for (int j = 1; j <= n; ++j) {
  17. order -= valid[j];
  18. // 判断这个数是否有用过
  19. if (!order) {
  20. ans += (j + '0');
  21. valid[j] = 0;
  22. break;
  23. }
  24. }
  25. // k = k - k/factorial[n-i] * factorial[n-i]
  26. k %= factorial[n - i];
  27. }
  28. return ans;
  29. }
  30. };