题目
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 _k_th 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 = 3Output: "213"
Example 2:
Input: n = 3, k = 3Output: "213"
题意
按字典序输出一个递增序列的第k个排列。
思路
对于n个数的排列,只有当后面n-1个数完成一次全排列后,才会对第一个数进行更替,即更换周期cycle为(n-1)!,且第一个数字是按照n个数中从最小数到最大数依次更替的。令 ,则排在第一位的数字是这n个数中的第count大,将该数字加入结果序列。每次得到第一位数字后,缩小n的规模求剩下n-1个数中应当排在第一位的数,同时要更新n-1个数中要求的第k个排列
。
笨办法:也可以结合0031. Next Permutation (M),从递增序列开始依次计算下一个排列。
代码实现
Java
公式计算
class Solution {public String getPermutation(int n, int k) {StringBuilder ans = new StringBuilder();boolean[] used = new boolean[n]; //标记剩下的数字while (n >= 1) {// 注意n=1时实际周期为0,将其周期设为1便于合并处理int cycle = n == 1 ? 1 : factorial(n - 1);int count = (k - 1) / cycle + 1;// 找到剩余数字中的第count大,并将其加入结果序列for (int i = 0; i < used.length; i++) {if (!used[i]) {if (count == 1) {ans.append(i + 1);used[i] = true;break;}count--;}}// 缩小待排列序列的规模n--;k = (k - 1) % cycle + 1;}return ans.toString();}private int factorial(int n) {int ans = 1;while (n != 1) {ans *= n--;}return ans;}}
nextPermutation
class Solution {public String getPermutation(int n, int k) {char[] a = new char[n];for (int i = 0; i < n; i++) {a[i] = (char) (i + 1 + '0');}int count = 1;while (count < k) {nextPermutation(a);count++;}return String.valueOf(a);}// 依照当前排列计算下一个排列private void nextPermutation(char[] a) {int i = a.length - 2;while (i >= 0 && a[i] >= a[i + 1]) {i--;}// i==-1说明整个数组是逆序排列,已经是字典序中的最后一个排列if (i == -1) {return;}int j = a.length - 1;while (a[j] <= a[i]) {j--;}swap(a, i, j);reverse(a, i + 1, a.length - 1);}private void reverse(char[] a, int left, int right) {while (left < right) {swap(a, left++, right--);}}private void swap(char[] a, int i, int j) {char temp = a[i];a[i] = a[j];a[j] = temp;}}
JavaScript
公式计算
/*** @param {number} n* @param {number} k* @return {string}*/var getPermutation = function (n, k) {let used = new Array(n)let ans = ''while (n > 0) {let cycle = n === 1 ? 1 : factorial(n - 1)let rank = Math.trunc((k - 1) / cycle) + 1let count = 0for (let i = 0; i < used.length; i++) {if (!used[i]) {count++if (count === rank) {ans += i + 1used[i] = truebreak}}}k = ((k - 1) % cycle) + 1n--}return ans}let factorial = function (n) {return n === 1 ? n : n * factorial(n - 1)}
nextPermutation
/*** @param {number} n* @param {number} k* @return {string}*/var getPermutation = function (n, k) {let count = 1let arr = new Array(n).fill(0).map((v, index) => index + 1)while (count !== k) {nextPermutation(arr)count++}return arr.join('')}let nextPermutation = function (arr) {let i = arr.length - 2while (i >= 0 && arr[i] >= arr[i + 1]) {i--}if (i === -1) {return}let j = arr.length - 1while (arr[i] >= arr[j]) {j--}[arr[i], arr[j]] = [arr[j], arr[i]]let left = i + 1,right = arr.length - 1while (left < right) {[arr[left++], arr[right--]] = [arr[right], arr[left]]}}
