Permutation Sequence

https://leetcode.com/problems/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):

  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.

解题思路:

开始把这题当成 Permutations ,直接dfs出所有组排列,然后去第k个,按照本题的意思,是一定会超时的,反正代码也写一下吧。

public class Solution {

    public String getPermutation(int n, int k) {

        List<String> permutationList = new ArrayList<String>();

        int[] visited = new int[n];

        dfs(permutationList, n, new StringBuffer(), 0, visited);

        return permutationList.get(k - 1);

    }



    public void dfs(List<String> permutationList, int n, StringBuffer current, int step, int[] visited){

        if(current.length() ==  n){

            permutationList.add(current.toString());

            return;

        }



        for(int i = 0; i < n; i++){

            if(visited[i] == 1){

                continue;

            }

            current.append(i + 1);

            visited[i] = 1;

            dfs(permutationList, n, current, step + 1, visited);

            current.deleteCharAt(current.length() - 1);

            visited[i] = 0;

        }

    }

}

然后再一想,对于上面的例子,比如k=5,那么前4次完全可以不算,因为第一位肯定是3了。为什么?因为以每个数字开头的组合,都一定有(n-1)!个。所以我们只要看这第k个数字在第m组的第n个就可以了。

这里m=(k - 1) / (n - 1)! + 1,n=(k-1) % (n - 1)! + 1。所以要求的第k个数字,一定是mxxxxxx的形式,而且在这xxxxxx的组合中,是第n个。

代码写出来,仍然超时。

public class Solution {

    public String getPermutation(int n, int k) {

        List<String> permutationList = new ArrayList<String>();

        int[] visited = new int[n];

        int factorial = fac(n - 1);

        int base = (k - 1) / factorial;

        int kth = (k - 1) % factorial + 1;

        

        visited[base] = 1;

        

        dfs(permutationList, n, new StringBuffer(String.valueOf(base + 1)), kth, visited, base);

        

        return permutationList.get(kth - 1);

    }



    public void dfs(List<String> permutationList, int n, StringBuffer current, int kth, int[] visited, int base){

        if(current.length() ==  n){

            permutationList.add(current.toString());

            return;

        }

        

        if(permutationList.size() == kth){

            return;

        }



        for(int i = 0; i < n; i++){

            if(visited[i] == 1){

                continue;

            }

            current.append(i + 1);

            visited[i] = 1;

            dfs(permutationList, n, current, kth + 1, visited, base);

            current.deleteCharAt(current.length() - 1);

            visited[i] = 0;

        }

    }

    

    public int fac(int n){

        int result = 1;

        for(int i = 1; i <= n; i++){

            result *= i;

        }

        return result;

    }

}

这时才想到,上面的思路不正是一个递归思路吗?或者迭代,这里都比较简单。我们对于第一位数字可以如此确定,后面所有位的数字也都可以这么确定了。

不能忘记的是,还是要有个去重的问题,当前第k个数字往前,如果已经选择过x个了,那么当前数字就是k+x。

public class Solution {

    public String getPermutation(int n, int k) {

        int[] visited = new int[n];

        return generate(n, k, visited);

    }

    

    public String generate(int n, int k, int[] visited){

        if(n == 0){

            return "";

        }

        int factorial = fac(n - 1);

        int base = (k - 1) / factorial;

        int kth = (k - 1) % factorial + 1;

        //除去前面已经选择过的数字

        int temp = 0;

        for(int i = 0 ; i < visited.length; i++){

            if(visited[i] == 1){

                base++;

            }

            if(i == base){

                break;

            }

        }

        visited[base] = 1;

        return String.valueOf(base + 1) + generate(n - 1, kth, visited);

    }

    

    public int fac(int n){

        int result = 1;

        for(int i = 1; i <= n; i++){

            result *= i;

        }

        return result;

    }

}

update 2015/06/04:

二刷,写了个迭代的。

public class Solution {

    public String getPermutation(int n, int k) {

        String res = "";

        int[] visited = new int[n + 1];

        for(int i = 0; i < n; i++) {    //从左往右迭代到第i位

            int bucketSize = fac(n - 1 - i);    //第i位的桶大小

            int digit = (k - 1) / bucketSize + 1;   //应该在第几个桶,这一位就是digit,但是要去掉已经选中的数字

            k = k - bucketSize * (digit - 1);   //方法1,剩下里面在第k个

            k = (k - 1) % bucketSize + 1;   //方法2,剩下里面在第k个

            for(int j = 1; j <= digit; j++){

                if(visited[j] == 1){

                    digit++;

                }

            }

            visited[digit] = 1;

            res = res + String.valueOf(digit);

        }

        return res;

    }

    

    public int fac(int n) {

        int res = 1;

        for(int i = 1; i <= n; i++) {

            res *= i;

        }

        return res;

    }

}

 

你可能感兴趣的:(sequence)