问题
例子
思路
-
方法1
因为for i in range(1,n)时,回溯获取的都是从下到大的,可以采用回溯,同时记录拿到了第几个元素
-
方法2
对每一位数进行定位第几个按下标的方式: k=k-1
有个候选数组 list
未确定的数字有n~1,则某未确定数字后面有n-1~0个数字
假如给定题目为(5,46)。固定第一位数,后面4位的全排列数为24,46/24==1,即处于候选数组的下标1,取出2并从list中删掉,对于固定第二位数,(46-24*1)/6==4,即处于list的下标4(此时列表移除了已确定的数字2),即第2位数为5.同理,可依次推理出最后结果为“25341”.总复杂度为O(n)
代码
//方法1
class Solution {
private String res="";
private int kk=1;//先比较再return,第一个元素是1
public String getPermutation(int n, int k) {
StringBuilder sb = new StringBuilder();
boolean[] used=new boolean[n+1];
get(n,used,sb,0,k);
return res;
}
public void get(int n, boolean[] used, StringBuilder sb, int c, int k) {
if(c==n && kk==k){
res=sb.toString();
kk++;
return;
}else if(c==n) {
kk++;
return;
}else {
c++;
for(int i=1; i<=n; i++) {
if(!used[i]){
sb.append(i);
used[i]=true;
get(n,used,sb,c,k);
sb.deleteCharAt(sb.length()-1);
used[i]=false;
}
}
}
return;
}
}
//方法2
class Solution {
public String getPermutation(int n, int k) {
StringBuilder sb = new StringBuilder();
//候选数字
List<Integer> list = new ArrayList<>();
//阶乘结果
int[] jiec = new int[n+1];
jiec[0]=1;
int ji=1;
for(int i=1; i<=n; i++) {
list.add(i);
ji*=i;
jiec[i]=ji;
}
k--;//转换为下标模式, i为分母涉及的数字个数
for(int i=n-1; i>=0; i--) {
int index=k/jiec[i];//从下标0开始,是第一个,后面有n-1个数字,
k=k%jiec[i];
n=n-1;
sb.append(list.remove(index));
}
return sb.toString();
}
}