Description
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.
Examples
Example1:
Input: n = 3, k = 3
Output: “213”
Example2:
Input: n = 4, k = 9
Output: “2314”
解题思路
如果先做递归再从保存的序列中抽取对应的字符串明显会占用过多的内存、耗费过多的时间
经过观察,不难发现
k
k
k 和
n
n
n 的规律
以
n
=
4
n = 4
n=4 为例,初始排列中位于第一位的数存在显而易见的规律
pos | 0 | 1 | 2 | 3 |
---|---|---|---|---|
1 | 2 | 3 | 4 | |
1 | 2 | 4 | 3 | |
1 | 3 | 2 | 4 | |
1 | 3 | 4 | 2 | |
1 | 4 | 2 | 3 | |
1 | 4 | 3 | 2 | |
2 | 1 | 3 | 4 | |
2 | 1 | 4 | 3 | |
2 | 3 | 1 | 4 | |
2 | 3 | 4 | 1 | |
2 | 4 | 1 | 3 | |
2 | 4 | 3 | 1 | |
3 | 1 | 2 | 4 | |
3 | 1 | 4 | 2 | |
3 | 2 | 1 | 4 | |
3 | 2 | 4 | 1 | |
3 | 4 | 1 | 2 | |
3 | 4 | 2 | 1 | |
4 | 1 | 2 | 3 | |
4 | 1 | 3 | 2 | |
4 | 2 | 1 | 3 | |
4 | 2 | 3 | 1 | |
4 | 3 | 1 | 2 | |
4 | 3 | 2 | 1 |
每个数 都对应了
(
n
−
1
)
!
(n-1)!
(n−1)! 个不同条目,也就是说,
k
k
k位置对应的第一个数一定是
k
/
n
k / n
k/n
如第1个位置一定是1,第9个位置一定是2
在确定了第一个数之后,就可以以相同的方式处理后面的数,以 k = 9 k = 9 k=9 为例,第一位确定后,后面的数字为
pos | 1 | 2 | 3 |
---|---|---|---|
1 | 3 | 4 | |
1 | 4 | 3 | |
3 | 1 | 4 | |
3 | 4 | 1 | |
4 | 1 | 3 | |
4 | 3 | 1 |
可以用相同的方式处理之后的每一位
自己做的时候选用Arraylist来进行剩余数字的存放,可以通过get和remove等方法轻松的获取对应位置的数字(代码1)
但是速度不行,在看了submission后,发现用StringBuilder类,在相同方法下,可以快速许多(代码2)
注意点:
- 首位对应的每个条目数为 ( n − 1 ) ! (n - 1)! (n−1)! 而不是 n − 1 n-1 n−1
代码1
class Solution {
public int factorial(int num){
int i = 1;
int sum = 1;
while(i < num){
sum = i * sum;
i++;
}
return sum;
}
public String getPermutation(int n, int k) {
List<Integer> ls = new ArrayList<>();
int i = 1;
while(i <= n){
ls.add(i);
i++;
}
int num = factorial(n);
k = k - 1;
List<String> temp = new ArrayList<>();
while(n > 0){
int pos = k / num;
temp.add(ls.get(pos) + "");
ls.remove(pos);
n = ls.size();
if(n <= 0)
break;
k = k % num;
num = num / n;
}
String answer = "";
for(i = 0; i < temp.size(); i++){
answer = answer + temp.get(i);
}
return answer;
}
}
代码2
class Solution {
public String getPermutation(int n, int k) {
int[] f = new int[n];
f[0] = 1;
for( int i = 1; i < n; i++)
f[i] = i * f[i-1];
StringBuilder sb = new StringBuilder();
boolean[] used = new boolean[n+1];
k--;
for( int i = n-1; i >= 0; i--){
int K = k / f[i];
k -= K * f[i];
K++;
int j = 0;
while(K > 0){
j++;
if( !used[j])
K--;
}
used[j] = true;
sb.append(j);
}
return sb.toString();
}
}