题目描述
给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。
说明:
给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。
示例:
输入: n = 3, k = 3
输出: “213”
总结
回溯剪枝优化思路详解
剪枝是优化回溯的重要手段
想到很容易,但具体写出来很难,第一时间我也想到了用阶乘优化,但却写不出来。
其实到头来,实现还是比较简单,但重要的是动手去画图,动手去写草稿,动手去写代码。
Sample & Demo Code
public class Solution {
int[] factorial = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
public String getPermutation(int n, int k) {
int[] nums = new int[n];
boolean[] used = new boolean[n];
for(int i = 0; i < n; i++)
nums[i] = i+1;
return dfs(nums, used, k, new ArrayList<>());
}
private String dfs(int[] nums, boolean[] used, int k, List<String> pre) {
if (pre.size() == nums.length) {
StringBuilder sb = new StringBuilder();
for (String c : pre) {
sb.append(c);
}
return sb.toString();
}
int ps = factorial[nums.length - 1 - pre.size()];
for (int i = 0; i < nums.length; i++) {
if(used[i]) continue;
if (ps < k) {
k -= ps;
continue;
}
pre.add(nums[i]+"");
used[i] = true;
return dfs(nums, used, k, pre);
}
throw new RuntimeException("参数错误");
}
}
ERROR Code(超时)
class Solution {
String res;
int count = 0;
public String getPermutation(int n, int k) {
List<Integer> sample = new ArrayList();
for(int i = 1; i <= n; i++)
sample.add(i);
helper(k, sample, new ArrayList<>());
return res;
}
private void helper(int k, List<Integer> sample, List<Integer> temp) {
if(temp.size() == sample.size()) {
count += 1;
if(count == k) {
// System.out.println("?");
res = L2s(temp);
return;
}
}
for(int i = 0; i < sample.size(); i++) {
int sg = sample.get(i);
if(!temp.contains(sg)) {
temp.add(sg);
helper(k, sample, temp);
temp.remove(temp.size()-1);
}
}
}
private String L2s(List<Integer> temp) {
StringBuilder sb = new StringBuilder();
for(int i : temp)
sb.append(i);
return sb.toString();
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence