- 第k个排列
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
说明:
给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。
示例 1:
输入: n = 3, k = 3
输出: “213”
示例 2:
输入: n = 4, k = 9
输出: “2314”
观察全排列性质
n
的全排列有n!
种方案n
的全排列 是由1 xxx
和2 xxx
和3 xxx
等等一直到n xxx
组成的
n=3
的解空间树和第k=4
个排列如下图
因此我们可以dfs
加上剪枝,直接找到第k
个全排列路径
每次累加节点子树的个数,步步逼近叶子节点即可,可用循环实现 O(n^2)
c++代码实现
int n;
void dfs(string& ans, int k) { //dfs枚举每一位数字
if(ans.size() >= n) return ;
int sum = 0, i = 0;
for(i=1; i<=n; i++) {
if(vis[i]) continue ;
if(sum+a[n-ans.size()-1] >= k) break;
sum += a[n-ans.size()-1];
}
vis[i] = true;
ans.push_back('0'+i);
dfs(ans, k-sum);
}
string getPermutation(int n, int k) {
memset(vis, false, sizeof(vis));
this->n = n;
a[1] = a[0] = 1;
for(int i=2; i<=9; i++) //递推N阶
a[i] = a[i-1] * i;
string ans;
dfs(ans, k);
return ans;
}
java代码
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
class Solution {
static int a[] = new int[16];
static boolean vis[] = new boolean[16];
int n = 0;
void dfs(StringBuilder ans, int k) {
if(ans.length() >= n) return ;
int i = 0, sum = 0;
for(i=1; i<=n; i++) {
if(vis[i]) continue ;
if(sum+a[n-ans.length()-1] >= k) break;
sum += a[n-ans.length()-1];
}
vis[i] = true;
ans.append(i);
dfs(ans, k-sum);
}
public String getPermutation(int n, int k) {
this.n = n;
Arrays.fill(vis, false);
a[0] = a[1] = 1;
for(int i=2; i<=9; i++) a[i] = a[i-1]*i;
StringBuilder ans = new StringBuilder();
dfs(ans, k);
return ans.toString();
}
}
public class Main {
public static final boolean debug = true;
public static String INPATH = "C:\\Users\\majiao\\Desktop\\test.txt",
OUTPATH = "C:\\Users\\majiao\\Desktop\\out.txt";
public static StreamTokenizer tok;
public static BufferedReader cin;
public static PrintWriter cout;
public static long start_time = 0, out_time = 0;
public static int n, m, K, Q, MAXN = (int)1e5+7, INF = 0x3f3f3f3f;
public static byte buf[] = new byte[MAXN];
public static void main(String[] args) throws IOException {
main_init();
if(debug) { start_time = System.currentTimeMillis(); }
if(false) { System.setOut(new PrintStream(OUTPATH)); }
Solution s = new Solution();
cout.printf("%s\n", s.getPermutation(4, 9));
if(debug) {
out_time = System.currentTimeMillis();
cout.printf("run time : %d ms\n", out_time-start_time);
}
cout.flush();
}
public static void main_init() {
try {
if (debug) {
cin = new BufferedReader(new InputStreamReader(
new FileInputStream(INPATH)));
} else {
cin = new BufferedReader(new InputStreamReader(System.in));
}
cout = new PrintWriter(new OutputStreamWriter(System.out));
// cout = new PrintWriter(OUTPATH);
tok = new StreamTokenizer(cin);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String next_str() {
try {
tok.nextToken();
if (tok.ttype == StreamTokenizer.TT_EOF)
return null;
else if (tok.ttype == StreamTokenizer.TT_NUMBER) {
return String.valueOf((int)tok.nval);
} else if (tok.ttype == StreamTokenizer.TT_WORD) {
return tok.sval;
} else return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static int read_int() {
String tmp_next_str = next_str();
return null==tmp_next_str ? -1 : Integer.parseInt(tmp_next_str);
}
public static long read_long() { return Long.parseLong(next_str()); }
public static double read_double() { return Double.parseDouble(next_str()); }
public static BigInteger read_big() { return new BigInteger(next_str()); }
public static BigDecimal read_dec() { return new BigDecimal(next_str()); }
}