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:
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note:
- Given n will be between 1 and 9 inclusive.
- Given k will be between 1 and n! inclusive.
Example 1:
Input: n = 3, k = 3 Output: "213"Example 2:
Input: n = 4, k = 9 Output: "2314"
第K个排列。题意是给你一个数字N(比如N = 3),如果输出1到N的全排列,结果会是类似这样,
"123"
"132"
"213"
"231"
"312"
"321"
现在给你一个数字N和一个数字K,请你输出的是这个全排列里面的第K项。
我参考了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 }