X Tutup
M tags: Math, Backtracking TODO: what about regular DFS/backtracking to compute the kth? dfs(rst, list, candiate list, k) k是permutation的一个数位。而permutation是有规律的。 也就是说,可以根据k的大小来判断每一个数位的字符(从最大数位开始,因为默认factorio从最大数位开始变化)。 于是先求出n!, 然后 k/n!就可以推算出当下这一个数位的字符。然后分别把factorio 和 k减小。 另外, 用一个boolean[] visited来确保每个数字只出现一次。 这个方法比计算出每个permutation要efficient许多。 ``` /* 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. Hide Tags Backtracking Math Hide Similar Problems (M) Next Permutation (M) Permutations */ /* Correct solution is to reduce k, and manipulate the sequence http://www.jiuzhang.com/solutions/permutation-sequence/ Thoughts: k is the sum of possibilities. Based on attempt1, attempt2, we understand that each digit leads a differnet sets of possibilities. The total is n! For example, factorio = # of a paticular set of possibilities, and remain = (k / factorio) means how any sets are there. If remain == 0, that means factorio has more possibiities than k (factorio > k) so there is nothing changed on 1st char position. For example, if given [1,2,3], then the string will end up as '1xx'. With the above fact, we can find out each char by calculate k vs. factorio. Note, each round, the factorio itself need to reduced. */ public class Solution { public String getPermutation(int n, int k) { if (n <= 0 || k <= 0) { return ""; } StringBuffer sb = new StringBuffer(); boolean[] visited = new boolean[n]; //Largest possible number of posibilities, n! int factorio = 1; for (int i = 1; i < n; i++) { factorio *= i; } //Put k into 0-base k = k - 1; for (int i = 0; i < n; i++) { int index = k / factorio; k = k % factorio; for (int j = 0; j < n; j++) { if (!visited[j]) { if (index == 0) { visited[j] = true; sb.append((char)('0' + j + 1)); break; } else { index--; } } } if (i < n - 1) { factorio = factorio / (n - i - 1); } } return sb.toString(); } } /* Based on attempt1, we can actually find every index in front by calling getPermutation(n,k) recursivly Still timeout */ public class Solution { public String getPermutation(int n, int k) { if (n <= 0 || k <= 0) { return ""; } ArrayList nums = new ArrayList(); for (int i = 1; i <= n; i++) { nums.add(i); } int frontInd = 0; for (; frontInd < nums.size(); frontInd++) { //find max # of permutations that's less than k, and start permutation with that perticular n at index 0. int factorio = 1; for (int i = 1; i < n; i++) { factorio = factorio * i; } int startInd = frontInd; int numPermute = factorio; while (numPermute < k) { numPermute += factorio; startInd++; } if (startInd != frontInd) { int temp = nums.get(startInd); nums.remove(startInd); nums.add(frontInd, temp); k = k - numPermute; n--; } } StringBuffer sb = new StringBuffer(); for (int num : nums) { sb.append(num); } return sb.toString(); } } /* Attempt1: timeout based on k[1 ~ k], find the max x that has x! < k, where x = [1 ~ n] then swap (x + 1) and 1, start permutation, and find the (k - x!)th */ public class Solution { public String rst = ""; public int index = 0; public String getPermutation(int n, int k) { if (n <= 0 || k <= 0) { return ""; } int[] nums = new int[n]; for (int i = 0; i < nums.length; i++) { nums[i] = i + 1; } //find max # of permutations that's less than k, and start permutation with that perticular n at index 0. int factorio = 1; for (int i = 1; i < n; i++) { factorio = factorio * i; } int startInd = 0; int numPermute = factorio; while (numPermute + factorio < k) { numPermute += factorio; startInd++; } if (startInd != 0) { int temp = nums[startInd];//findMax return value in [1 ~ n], and we need index nums[startInd] = nums[0]; nums[0] = temp; k = k - numPermute; } permute("", k, nums);// startInd + 1 is in [1 ~ n] return rst; } public void permute(String s, int k, int[] nums) { if (rst.length() != 0) { return; } if (s.length() == nums.length) { index++; if (index == k) { rst = s; } return; } for (int i = 0; i < nums.length; i++) { if (!s.contains(nums[i] + "")) { permute(s + nums[i], k, nums); } } } } ```
X Tutup