首页 > 代码库 > Leetcode: Permutation Sequence

Leetcode: 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.Note: Given n will be between 1 and 9 inclusive.

看到这道题,第一时间就联系到了Next Permutation. 那道题是让找下一个稍大的Permutation, 而这里是找从小到大第K大的Permutation, 而最小的Permutation我们明显知道,那么用Next Permutation做Subroutine,做K次,不就找到了所需的Permutation了吗。Next Permutation时间复杂度为O(N), 这里就是O(N*k).

代码里面把Int数组拷贝成一个char数组,是为了方便转换成String

 1 public class Solution { 2     public String getPermutation(int n, int k) { 3         if (n < 0) return""; 4         int[] num = new int[n]; 5         char[] numcopy = new char[n]; 6         for (int z=0; z<n; z++) { 7             num[z] = z + 1; 8         } 9         for (int i=2; i<=k; i++) {10             nextPermutation(num);11         }12         for (int z=0; z<n; z++) {13             numcopy[z] = (char)(‘0‘ + num[z]);14         }15         return new String(numcopy);16     }17     18     public void nextPermutation(int[] num) {19         if (num == null || num.length == 0 || num.length == 1) return;20         int i = num.length-2;21         while (i>=0 && num[i]>=num[i+1]) {22             i--;23         }24         if (i >= 0) {25             int j = i;26             while (j<num.length-1 && num[j+1]>num[i]) {27                 j++;28             }29             int temp = num[i];30             num[i] = num[j];31             num[j] = temp;32         }33         reverse(num, i+1);34     }35     36     public void reverse(int[] num, int k) {37         int start = k;38         int end = num.length - 1;39         while (start < end) {40             int temp = num[start];41             num[start] = num[end];42             num[end] = temp;43             start++;44             end--;45         }46     }47 }

我这个方法很直接,但是时间复杂度O(N*k)应该比较大,因为k是可以取值到N!的,虽然通过了OJ,但是还是不太好。 网上看到一些做法,均是把它当做一道找规律的数学题目。我们知道,n个数的permutation总共有n阶乘个,基于这个性质我们可以得到某一位对应的数字是哪一个。思路是这样的,比如当前长度是n,我们知道每个相同的起始元素对应(n-1)!个permutation,也就是(n-1)!个permutation后会换一个起始元素。因此,只要当前的k进行(n-1)!取余,得到的数字就是当前剩余数组的index,如此就可以得到对应的元素。如此递推直到数组中没有元素结束。实现中我们要维护一个数组来记录当前的元素,每次得到一个元素加入结果数组,然后从剩余数组中移除,因此空间复杂度是O(n)。时间上总共需要n个回合,而每次删除元素如果是用数组需要O(n),所以总共是O(n^2)。这里如果不移除元素也需要对元素做标记,所以要判断第一个还是个线性的操作。

Code Ganker做法(未深究)

 1 public String getPermutation(int n, int k) { 2     if(n<=0) 3         return ""; 4     k--; 5     StringBuilder res = new StringBuilder(); 6     int factorial = 1; 7     ArrayList<Integer> nums = new ArrayList<Integer>(); 8     for(int i=2;i<n;i++) 9     {10         factorial *= i;11     }12     for(int i=1;i<=n;i++)13     {14         nums.add(i);15     }16     int round = n-1;17     while(round>=0)18     {19         int index = k/factorial;20         k %= factorial;21         res.append(nums.get(index));22         nums.remove(index);23         if(round>0)24             factorial /= round;25         round--;26     }27     return res.toString();28 }

 

Leetcode: Permutation Sequence