[LeetCode] 60. Permutation Sequence

The set [1, 2, 3, ..., n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order, we get the following sequence for n = 3:

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

Given n and k, return the kth permutation sequence.

Example 1:

Input: n = 3, k = 3
Output: "213"

Example 2:

Input: n = 4, k = 9
Output: "2314"

Example 3:

Input: n = 3, k = 1
Output: "123"

Constraints:

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

排列序列。

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

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

"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/permutation-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我参考了LC讨论区的最高票答案。他的思路基本上是逐位确定每一位上应该是什么数字,然后再一点点 append 起来的。首先如果 N = 4,那么也就是有1,2,3,4四个数字,他的 permutation 应该类似如下这样,同时4的全排列的总数是4! = 24

  • (0)1 + {2, 3, 4的全排列} = 6
  • (1)2 + {1, 3, 4的全排列} = 6
  • (2)3 + {1, 2, 4的全排列} = 6
  • (3)4 + {1, 2, 3的全排列} = 6

如果给你一个数字 N,你很容易就知道这 N 个数字的全排列的个数是N!。同时如果你知道全排列里面第一个数字的话,那么你接下来也只需要在(N - 1)! 个结果中就能确定你这个全排列到底是什么了。这就是为什么这个题能逐位确定每一位上应该是什么数字的原因。

还是假设 N = 4,那么全排列的个数是 4! = 24;如果你能确定第一个数字的话,那么你可以将要找的范围缩小到三个数字的全排列,即 3! = 6。但是如何得知第一个数字呢?假如你要找的 K = 14,先将 K--,得到 13(因为数组中的index一般是从0开始的)。K / (N - 1)! = K / 3! = 13 / 3! = 13 / 6 = 2,意味着第一个数字的index = 2,也就意味着第一个数字其实是3

知道第一个数字是3之后,也就知道了接下来是在{1, 2, 4的全排列}里面找结果了。如果一直递归地往下想,要找的也就是

(0)1 + {2, 4的全排列} = 2

(1)2 + {1, 4的全排列} = 2

(2)4 + {1, 2的全排列} = 2

但是此时K已经不是13了,而是K % (N - 1)! = 13 % 3! = 13 / 6 = 1。

下一轮K / (N - 1)! = 1 / 2! = 1 / 2 = 0,意味着第二个数字的index = 0,第二个数字是1是在1 + {2, 4的全排列}里面接着找。此时K = K % (N - 1)! = 1 % 2! = 1 % 2 = 1。

此时在3 + {1, 2, 4的全排列}里面继续找。既然K = 0,那么在3 + 1 + {2, 4的全排列}里面的index又是多少呢?

第三个数字的index = K / (N - 1)! = 1 / 1! = 1,意味着第三个数字的index = 2第三个数字是1,下一轮因为只剩一个数字2,所以结果就是3142。

时间O(n^2)

空间O(n)

Java实现

 1 class Solution {
 2     public String getPermutation(int n, int k) {
 3         List<Integer> res = new ArrayList<>();
 4         for (int i = 1; i <= n; i++) {
 5             res.add(i);
 6         }
 7         int[] fact = new int[n];
 8         fact[0] = 1;
 9         for (int i = 1; i < n; i++) {
10             fact[i] = i * fact[i - 1];
11         }
12         // [1, 1, 2, 6]
13         k = k - 1;
14         StringBuilder sb = new StringBuilder();
15         for (int i = n; i > 0; i--) {
16             int index = k / fact[i - 1];
17             k = k % fact[i - 1];
18             sb.append(res.get(index));
19             res.remove(index);
20         }
21         return sb.toString();
22     }
23 }

 

LeetCode 题目总结

posted @ 2020-06-21 06:20  CNoodle  阅读(407)  评论(0编辑  收藏  举报