您的位置:首页 > 其它

LeetCode60 n个数的排列组合找出第k个排列

2017-12-06 15:38 453 查看
觉得这道题有必要,我二次回顾,数学。。。。

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 (ie, 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.

第一种解决办法,数学方法解决

//相当于因式分解
public String getPermutation(int n, int k) {
int[] factorial = new int
;

//因式分解需要的基数
for (int i = 0; i < n; i++) {
if (i == 0) {
factorial[i] = 1;
continue;
}
factorial[i] = factorial[i - 1] * (i);
}
//1,1,2,6,24
//1*0+1*1+2*2+6*3+24*4=119
//而我们实际需要的数是:1、2、3、4、5,但他们的组合序列就相当于0、1、2、3、4的组合,只是各自加1而已。
//二者的不同还在于,0-4的k的表是范围是从0-119,而我们的k是从1-120,所以变换关系是k-1。

StringBuilder res = new StringBuilder();
boolean[] used = new boolean
;
int i = n - 1;
while (i >= 0) {
int digit = (k - 1) / factorial[i];//变换关系k-1
res.append(findKth(used, digit));//先取最高位的值
k -= digit * factorial[i--];
}

return res.toString();
}
//再次强调下,数组是用的地址,而我们传递的对象就是普通的参数
public int findKth(boolean[] used, int digit) {
int res = -1;
while (digit >= 0) {
if (!used[++res]) { //从小到大的去取值,同时进行标记
digit--;
}
}
used[res] = true;
return res + 1;//从0-4,变为1-5

}


第二种方法,我的坑呀,每次都是先想到递归

首先只要两个元素换一下位置,就会使得count++的,假如我取得是1,那么剩下的【2、3、4、5】,再次进行重复的操作,还有的就是递归很容易超时,如何根据k值来减少重复,是很必要的,这个还可以优化,比如说不是用set,而是用上面的boolean[] used 下坐标和数值的位置关系。

public String getPermutation(int n, int k) {
String str = "";

TreeSet<Integer> set = new TreeSet<>();

for (int i = 1; i <= n; i++) {
str += i;
set.add(i);
}
if (k == 1 || n==1) {
//System.out.println(k +": "+ str);
return str;
}
str = "";

return getShort(set,k,str);

}
public int count;
public String getShort(TreeSet<Integer> set,int k,String str){
if(set.size()==2){
//System.out.println(str + set.first()+ set.last());
count ++;
if(count == k){
return str + set.first()+ set.last();
}
//System.out.println(str + set.last()+ set.first());
count ++;
if(count == k){
return str + set.last()+ set.first();
}
return null;

}else{

Object[] array = set.toArray();
for(int i=0;i<array.length;i++){
Integer t = (Integer)array[i];
set.remove(t);
str=str+t;
int z = count;
String ret = getShort(set,k,str);
if(count == k){
return ret;
}
set.add(t);
str=str.substring(0, str.length()-1);
if(k>(z+((array.length)*(count-z)))){
count =z+array.length * (count-z);
i=array.length-1;
}
}
return null;

}
}


我想过用set的迭代器遍历所有值,但是不可以,我觉得应该和我这个迭代冲突了,我也不知道为啥,一上午终于解决这个问题了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode 回顾