地址:https://leetcode-cn.com/problems/permutation-sequence/
我寫的題解地址:https://leetcode-cn.com/problems/permutation-sequence/solution/hui-su-jian-zhi-python-dai-ma-java-dai-ma-by-liwei/
思路:從高到低確定每一位數字,這裏可以使用“回溯”方法中的“剪枝”技巧。
方法一:藉助“回溯”方法中的“剪枝”技巧
Java 代碼:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
/**
* 記錄數字是否使用過
*/
private boolean[] used;
/**
* 階乘數組
*/
private int[] factorial;
private int n;
private int k;
/**
* 從根結點到葉子結點的路徑
*/
private List<Integer> path;
public String getPermutation(int n, int k) {
this.n = n;
this.k = k;
used = new boolean[n + 1];
Arrays.fill(used, false);
// 計算階乘數組
factorial = new int[n + 1];
factorial[0] = 1;
for (int i = 1; i <= n; i++) {
factorial[i] = factorial[i - 1] * i;
}
path = new ArrayList<>(n);
dfs(0);
StringBuilder stringBuilder = new StringBuilder();
for (Integer c : path) {
stringBuilder.append(c);
}
return stringBuilder.toString();
}
/**
* @param index 在這一步之前已經選擇了幾個數字,其值恰好等於這一步需要確定的索引位置
* @return
*/
private void dfs(int index) {
if (index == n) {
return;
}
// 還未確定的數字的全排列的個數,第 1 次進入的時候是 n - 1
int cnt = factorial[n - 1 - index];
for (int i = 1; i <= n; i++) {
if (used[i]) {
continue;
}
if (cnt < k) {
k -= cnt;
continue;
}
path.add(i);
used[i] = true;
dfs(index + 1);
}
}
}
方法二:模擬鏈表直接計算求解
事實上,上面的過程也可以循環實現,只不過需要藉助一個列表,每次選出一個數,就將這個數從列表裏面拿出。因爲這個列表要支持頻繁的刪除操作,因此使用雙鏈表,在 Java 中 LinkedList 就是使用雙鏈表實現的。
作者:liweiwei1419
鏈接:https://leetcode-cn.com/problems/permutation-sequence/solution/hui-su-jian-zhi-python-dai-ma-java-dai-ma-by-liwei/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
Java 代碼:
import java.util.LinkedList;
import java.util.List;
public class Solution {
public String getPermutation(int n, int k) {
// 注意:相當於在 n 個數字的全排列中找到索引爲 k - 1 的那個數,因此 k 先減 1
k --;
int[] factorial = new int[n];
factorial[0] = 1;
// 先算出所有的階乘值
for (int i = 1; i < n; i++) {
factorial[i] = factorial[i - 1] * i;
}
// 因爲要頻繁做刪除,使用鏈表
List<Integer> nums = new LinkedList<>();
for (int i = 1; i <= n; i++) {
nums.add(i);
}
StringBuilder stringBuilder = new StringBuilder();
// i 表示剩餘的數字個數,初始化爲 n - 1
for (int i = n - 1; i >= 0; i--) {
int index = k / factorial[i] ;
stringBuilder.append(nums.remove(index));
k -= index * factorial[i];
}
return stringBuilder.toString();
}
}