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 (ie, 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.
思路:有一种方法,我们可以递归求解出所有的排列,然后取出第k个,但是这么操作,既复杂,也没有必要。
我们来一起找找数学规律,n个数的排列总共有n!个组合,基于这个性质我们可以得到某一位对应的数字是哪一个。如,当前长度是n,我们知道每个相同起始元素都对应(n-1)!个排列,也就是每隔(n-1)!个排列就会按照大小顺序更换一个起始元素。因此,我们只要对当前的k对(n-1)!取余,得到的数字就是当前剩余数组的index, k /(n-1)!就是当前元素。如此递归下去,知道数组中没有元素。我们需要维护一个数组记录当前的元素,每次得到一个元素加入结果数组,就要把它从剩余数组中移除,剩余数组重新排序,接下来依然按照index取元素。
假设有n个元素,第K个permutation是
if(round > 0) factorial /= round;
Attention:
1. k--; 让下标从0开始,这样就统一了下标和数组下标索引。
2. 每次得到的元素,转成字符后,添加到结果字符串中。用加‘0’的方式
ret += ('0' + nums[index]); //转成字符添加进字符串3. vector的erase函数 删除后,会改变容器大小和排序。
iterator erase (const_iterator position); iterator erase (const_iterator first, const_iterator last);
参数必须是迭代器。
nums.erase(nums.begin() + index); //参数必须是迭代器4. 再递减 (n-1)!时,需要判断分母是否大于0.
if(round > 0) factorial /= round;5. 我们需要判断到round = 0, 从 (n-1)! 到 0!, 总共添加n回,才能得到结果字符串
while(round >= 0)复杂度:O(N), 进行N各回合。
AC Code:
class Solution { public: string getPermutation(int n, int k) { if(n <= 0) return ""; //转换成从0开始 k--; string ret; int factorial = 1; //计算(n-1)! for(int i = 2; i < n; i++) { factorial *= i; } vector<int> nums; for(int i = 1; i <= n; i++) { nums.push_back(i); } int round = n - 1; while(round >= 0) { int index = k / factorial; k %= factorial; ret += ('0' + nums[index]); //转成字符添加进字符串 nums.erase(nums.begin() + index); //参数必须是迭代器 if(round > 0) factorial /= round; round--; } return ret; } };
[C++]LeetCode: 114 Permutation Sequence(返回第k个阶乘序列——寻找数学规律)
原文地址:http://blog.csdn.net/cinderella_niu/article/details/42927119