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"
题目理解:
找出由1 ~ n组成的数组的第k个排列
解题思路:
使用改进的序数法可以解决这个问题,可以参考这个博客https://blog.csdn.net/BabyNumber/article/details/44217255。
首先将k转化为一个特殊的形式,我们使用的是十进制数,每一位的进制都是10,第i为的数字bit表示的bit*10^i,同理,二进制数每一位都是2进制,第i为数字bit表示的是bit*2^i。
这里的特殊进制是:第一位(十进制中的个位)数是2进制,第二位(百位)是3进制,以此类推,一直计算出这个数字的第k - 1位,计算的方法其实很简单,每一次取余,再做一次出发就行,具体看代码。
在一般的序数法中,特殊进制的k的每一位代表这个 数字 左边的逆序对数目(就是这个数字左边的比它大的数字的个数)
在改进的序数法中,特殊进制的k的每一位代表这个 位置 左边的逆序对数目(这个位置左边的,比放在这个位置的数大的数的个数)
具体的使用方法就是,先考虑排列的最左边的位置,从1开始,如果特殊进制k的第一位是i,那么将1变大i次,变大的意思是加1,但是如果得到的数字已经用过了,那么就多进行一次变大,将最终得到的数字放在当前位置上。
遍历所有的位置,就可以得到答案。
class Solution {
public String getPermutation(int n, int k) {
k--;
int[] record = new int[n];
for(int i = n - 2, j = 2; i > -1; i--, j++){
record[i] = k % j;
k /= j;
}
String str = "";
boolean[] visited = new boolean[n + 1];
for(int num : record){
//System.out.print(num + " ");
int cur = 1;
for(int i = 0; i < num; cur++){
if(!visited[cur])
i++;
}
while(visited[cur])
cur++;
visited[cur] = true;
str = str + cur;
}
//System.out.println();
return str;
}
}