2020年9月5日 第k个排列getPermutation
class Solution {
public String getPermutation(int n, int k) {
}
}
解题思路:
思路1,暴力算法
直接使用循环将每一种情况按照顺序列出,然后取出第k个元素,时间复杂度nXn!,这肯定不是一个好的方法,所以需要寻找一种更优秀的方法。
思路2,递归
其实我们可以非常简单地知道,第k个数的第1个数字是多少,比如:
n=5 k=54,由于n=5,我们可以知道共有5!种排列,那么以1开头的元素必定有4!个,那么我们可以知道以1开头的数字必定是比以2开头的数字小的,那么前面4!=24个都是以1开头,再后面的24个是以2开头,这里已经有48个了,所以第54个必定是以3开头的。
那么我们如何递归解决这道问题呢?
递归的思路,把大的问题化解成小的问题。
我们在上面已经会求出n=5 ,k =54时第k个排列的开头数字是3了。那么,第二个数字怎么得到呢?我们可以通过剩下的数字,4个,此时我们可以知道第49个到72个都是以数字3开头的,那么在这24个排列中,我们依然可以套用上面的方式,只是需要除掉数字3。
在这24个排列中,以1开头的依然面几个,只不过数量从4!下降到了3!,也就是6个,54是在第6个,所以刚好也是以1开头的。
依次类推,剩下的2,4,5组成的排列组合的第6个那么得到的就是5是第3个。
以2,4组成的排列组合的第二个,也就是4是四个数字。
最后一个是2。
得到的排列时31542。
我们用官方的方法验证一下。
代码实现:
String res="";
List<Integer> ints=new ArrayList<>();
public String getPermutation(int n, int k) {
//构建链表
for (int i=1;i<=n;i++){
ints.add(i );
}
recursion(k-1);
return res;
}
//递归方法,一个k表示取出排列的第k个组合
public void recursion(int k){
//我们自己获取n
int n=ints.size();
//递归结束条件
if (n==0)
return;
//得到阶乘
int nj=1;
for (int i=1;i<n;i++){
nj*=i;
}
//得到此时的数字是什么
int k1=k/nj;
//拼接上
res=res+ints.get(k1);
ints.remove(k1);
int k2=k%nj;
recursion(k2);
}