60. Permutation Sequence(第K个排列)

题目链接:https://leetcode.com/problems/permutation-sequence/

方法1:回溯,及时停止。

这种思路好想,代码也好写。

注意当count==K时,不要把原有的list里面的对象删除了。

AC 313ms beats 12.5% Java :)速度感人

class Solution {
    private int count=0;
    private List<Integer> list =new ArrayList();
    public String getPermutation(int n, int k) {
        boolean[] flag=new boolean[n+1];
        helper(n,k,flag);
        StringBuilder sb=new StringBuilder();
        for(int i : list){
            sb.append(String.valueOf(i));
        }
        return sb.toString();
        //return String.valueOf(list.size());
        
    }
    public void helper(int n,int k,boolean[] flag){
        if(count==k){
            return;
        }
        if(list.size()==n){
            count++;
        }
        for(int i=1;i<=n&&count!=k;i++){
            if(!flag[i]){
                list.add(i);
                flag[i]=true;
                helper(n,k,flag);
                flag[i]=false;
                if(count!=k)
                    list.remove(list.size()-1);  
            }
        }
        return ;
    }
}

方法二:找数学规律(逆康托排列)

由于二进制中 2的一次方对应0和1,依次类推,当我们拿到K时要先对K-1,

这样才能通过除法得到他正确的区间。

康托排列

然后我们通过逆康托排列来求解第K个数每一位的值。

准备条件:分别求解出1到N-1的阶乘的值保存在数组中。

易错点:  对Java的list来说,get(0)表示取出第一个元素。

list的remove易错点:remove()方法陷阱

有了这些准备条件,我们来尝试求解。

例1 {1,2,3,4,5}的全排列,并且已经从小到大排序完毕
(1)找出第96个数
    首先用96-1得到95,
    用95去除4! 得到3余23,
    有3个数比它小的数是4,
    所以第一位是4,
    用23去除3! 得到3余5,
    有3个数比它小的数是4但4已经在之前出现过了所以第二位是5,

   (4在之前出现过,所以实际比5小的数是3个)
    用5去除2!得到2余1,
    有2个数比它小的数是3,第三位是3,
    用1去除1!得到1余0,
    有1个数比它小的数是2,第二位是2,
    最后一个数只能是1,
    所以这个数是45321,
(2)找出第16个数
    首先用16-1得到15,
    用15去除4!得到0余15,
    用15去除3!得到2余3,
    用3去除2!得到1余1,
    用1去除1!得到1余0,
    有0个数比它小的数是1,
    有2个数比它小的数是3 ,但由于1已经在之前出现过了所以是4,

   (因为1在之前出现过了所以实际比4小的数是2)
    有1个数比它小的数是2 ,但由于1已经在之前出现过了所以是3,

    (因为1在之前出现过了所以实际比3小的数是1)
    有1个数比它小得数是2 但由于1,3,4已经在之前出现过了所以是5,

    (因为1,3,4在之前出现过了所以实际比5小的数是1)
    最后一个数只能是2
    所以这个数是14352
 

基本上例子看懂的话,程序不难写出来。

AC 6ms 99.96% Java:

class Solution {
    public String getPermutation(int n, int k) {
        List<Integer> list=new ArrayList();
        int[] factorial=new int[n+1];
        factorial[0]=1;
        for(int i=1;i<=n;i++){
            factorial[i]=factorial[i-1]*i;
            list.add(i);
        }
        StringBuilder sb =new StringBuilder();
        k--;//只需减一次即可。
        for(int i=n;i>0;i--){
            int temp=list.get(k/factorial[i-1]);
            k=k%factorial[i-1];
            if(i!=1){
                sb.append(String.valueOf(temp));
                list.remove(new Integer(temp));//如果不new一个Integer对象的话会出错。
                
            }else{
                sb.append(String.valueOf(list.get(0)));
            }
        }
        return sb.toString();
    }
}

猜你喜欢

转载自blog.csdn.net/God_Mood/article/details/88124708