LeetCode 60 第k个排列
LeetCode 60 第k个排列
题目描述:
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
示例:
输入: n = 3, k = 3
输出: "213"
输入: n = 4, k = 9
输出: "2314"
算法分析
做法:
从高位到低位依次考虑每一位;
对于每一位,从小到大依次枚举未使用过的数,确定当前位是几;
例子
n = 5,k = 40
第一位数:
k = 40
idx = 40 / 4! 上取整 = 2
因此第1位数放的是当前没有枚举过的第2个元素,即第1位数是 2
k -= (idx - 1) * 4! = 16
第二位数:
k = 16
idx = 16 / 3! 上取整 = 3
因此第2位数放的是当前没有枚举过的第3个元素,即第2位数是 4 (2已经被枚举过)
k -= (idx - 1) * 3! = 4
第三位数:
k = 4
idx = 4 / 2! 上取整 = 2
因此第3位数放的是当前没有枚举过的第2个元素,即第3位数是 3 (2已经被枚举过)
k -= (idx - 1) * 2! = 2
第四位数
k = 2
idx = 2 / 1! 上取整 = 2
因此第4位数放的是当前没有枚举过的第2个元素,即第4位数是 5 (2,3,4已经被枚举过)
k -= (idx - 1) * 1! = 1
第五位数
k = 1
idx = 1 / 0! 上取整 = 1
因此第5位数放的是当前没有枚举过的第1个元素,即第4位数是 1
k -= (idx - 1) * 0! = 1
因此答案是:"24351"
代码
class Solution {
public String getPermutation(int n, int k) {
boolean[] st = new boolean[10];
int[] f = new int[10];
f[0]=1;
//f[i] 表示 阶乘
// 1! = 1
// 2! = 2
// 3! = 6
for(int i=1;i<=n;i++) f[i] = f[i-1]*i;
String ans = "";
for(int i=n-1;i>=0;i--){
//第一步,计算idx
int idx = (k + f[i] - 1) / f[i]; //上取整
int count = 0;
for(int j=1;j<=n;j++){
if(st[j]) continue;
count++;
if(count==idx){
st[j] = true;
ans += j;
break;
}
}
k -= (idx - 1) * f[i];
}
return ans;
}
}

浙公网安备 33010602011771号