問題
例子
思路
-
方法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();
}
}