/** * summary: * approach 1 : dfs backtrack but TLE ! * * approach 2 : math * candidate: [1,2,3,4,...n] kth * 1. calculate block size : (n - 1)! * 2. renew candidate and k * new k = k % (n - 1)! * block i = k / (n - 1)! * remove i from candidate * ! corner case : * k % (n - 1)! = 0 -> k = block size, i = k / (n - 1)! - 1 * 3. when candidate.size == 1 we get the answer, else go to step 1 * * **/
package myapp.kit.leetcode.top200;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 60
* medium
* 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 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.
* Given k will be between 1 and n! inclusive.
* Example 1:
*
* Input: n = 3, k = 3
* Output: "213"
* Example 2:
*
* Input: n = 4, k = 9
* Output: "2314"
*
*
* @author huangdingsheng
* @version 1.0, 2020/6/30
*/
public class permutation_sequence_60 {
/**
* summary:
* approach 1 : dfs backtrack but TLE !
*
* approach 2 : math
* candidate: [1,2,3,4,...n] kth
* 1. calculate block size : (n - 1)!
* 2. renew candidate and k
* new k = k % (n - 1)!
* block i = k / (n - 1)!
* remove i from candidate
* ! corner case :
* k % (n - 1)! = 0 -> k = block size, i = k / (n - 1)! - 1
* 3. when candidate.size == 1 we get the answer, else go to step 1
*
* **/
/*appraoch1==========dfs backtrack========================*/
private static List<Integer> list;
public static String getPermutation(int n, int k) {
// init
list = new ArrayList<>();
int s1 = n;
int temp = n - 1;
while (temp >= 1) {
s1 = s1 * temp;
temp--;
}
if (k > s1 / 2) {
search2(n, "", new HashSet<>(), 0, s1 - k + 1);
} else {
search1(n, "", new HashSet<>(), 0, k);
}
return list.get(list.size() - 1).toString();
}
private static void search1(int n, String path, Set<String> set, int count, int k) {
if (list.size() == k) {
return;
}
if (count == n) {
list.add(Integer.valueOf(path));
return;
}
for (int i = 1; i <= n; i++) {
if (set.contains(String.valueOf(i))) {
continue;
}
String temp = path;
path += i;
set.add(String.valueOf(i));
search1(n, path, set, count + 1, k);
path = temp;
set.remove(String.valueOf(i));
}
}
private static void search2(int n, String path, Set<String> set, int count, int k) {
if (list.size() == k) {
return;
}
if (count == n) {
list.add(Integer.valueOf(path));
return;
}
for (int i = n; i >= 1; i--) {
if (set.contains(String.valueOf(i))) {
continue;
}
String temp = path;
path += i;
set.add(String.valueOf(i));
search2(n, path, set, count + 1, k);
path = temp;
set.remove(String.valueOf(i));
}
}
public static void main(String[] args) {
System.out.println(getPermutation(9, 142424));
}
/*approach2======================================================*/
public static String getPermutation2(int n, int k) {
List<Integer> candidate = new ArrayList<>();
for (int i = 1; i <= n; i++) {
candidate.add(i);
}
StringBuilder sb = new StringBuilder();
int idx = 0;
while (candidate.size() > 1) {
int blockSize = getFactorial(n - 1);
if (k % blockSize == 0) {
idx = k / blockSize - 1;
k = blockSize;
sb.append(candidate.get(idx));
candidate.remove(idx);
} else {
idx = k / blockSize;
k = k % blockSize;
sb.append(candidate.get(idx));
candidate.remove(idx);
}
n--;
}
sb.append(candidate.get(0));
return sb.toString();
}
private static int getFactorial(int n) {
int i = 1;
while (n > 1) {
i *= n;
n--;
}
return i;
}
}