Permutation Sequence

问题描述

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.

思考:

  • 1、序列123,排在第一位,其中,1在123中排第一位,2在23中排第一位,3在3中排第一位。
    112+111+110=0
    132,中1在123拍第一位,3在23中排第二位,2在2中排第一位。 112+211+110=1
    213中…. 212+111+110=2

    取A[i]表示result中第i个数在i到n 的大小排序(序号从0开始),则有k-1 = (n-1)! * A[0] + (n-2)! * A[1]…..1! * A[n-2] + 0! * A[n-1]$;其中,A[n - 1] 表示n到n的排序,因为只有一个数,所以A[n - 1]的序号为0;如k=3,result为213 :A[0..3] = 100,即(2在123中排序第2,1在13中排序第1,3在3中排序第1) 3 - 1 = 1 * 2!= 2。

    从A[0..n]推导result过程中,因为序号为A[n]从零开始,但是其排序位置为1, 即A[i]表示排序大小为k的数,则A[i]=k-1.所以,result[i] = A[i] + 1; 在确定result[i]之后,从i+1到n中,因为i..n中result[i],排k位,所以对i..n。 中每一位result[m] >= result[i],都使reslut[m]++;(如果后面的result = result[i],则在第i位计算排序时,第m位必定高于第i位,所以,让reuslt[m]++) 如213中,从后往前看,当计算到1时,1在13中排第一位(此时,result为011),所以让3那个位置+1,变为012,计算2时,2的排位应该为2(在123中),所以2的 reslut为2,然后往后看,此时result为(212),然后让3那个位置加1变为213, 即为正确的结果。(类似与在已排好序的数组中在插入第k个数,然后调整排序)

  • 2、对于 k1=(n1)!A[0]+(n2)!A[1].....1!A[n2]+0!A[n1] ; 第一位数为为(1..n)中的第k / (n - 1)!位,第二位数为(1..n)中除去第一位的第 k / (n - 2)位。其中, k = k% (n-1)! 以此类推。

代码

第一种:


public class Solution {
    public String getPermutation(int n, int k) {   
        k--;
        char[] result = new char[n];
        result[n - 1] = '1';      //n-1 表示A[n - 1],肯定在第一位      
        int factorial = 1;
        for(int i = 2; i < n + 1; i++){
            factorial *= i ;
            result[n - i] = (char)(k % factorial * i / factorial 
            + '1');  //表示reslut[n - i]中有多少个(i-1)!

            for(int j = n - i + 1; j < n; j++)
                result[j] += result[n - i] > result[j]? 0: 1;
             k -= k % factorial;
        }
        return new String(result);
    }
}

第二种

public class Solution {

    public String getPermutation(int n, int k) {

        List<Integer> list = new LinkedList<Integer>();
        for(int i = 0; i < 9; i++)
            list.add(i + 1);
        k--;
        int fact = 1;
        for(int i = 2 ; i <= n; i++)
            fact *= i;   
        StringBuffer sb = new StringBuffer();        
        for(int i = n ; i > 0; i--){
            fact /= i;
            sb.append(list.remove(k / fact));
            k %= fact;
        }
        return sb.toString();   
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值