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

觉得这道题有必要,我二次回顾,数学。。。。

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):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "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[n];
        
		//因式分解需要的基数
		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[n];
		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的迭代器遍历所有值,但是不可以,我觉得应该和我这个迭代冲突了,我也不知道为啥,一上午终于解决这个问题了。


阅读更多
换一批

没有更多推荐了,返回首页