LeetCode 60 Permutation Sequence
思路
-
采用Next Permutation的方法。
-
不难发现,总共有n!个permutation。按照第一个元素的值将permutation划分为不同的组,可见每组有(n-1)!个permutation。那么考虑通过这一特性,直接确定每个位置的值。以n为4,k为9,结果为2314举例。首先新建vector{1,2,3,4},根据第一个位置的值,将permutation分为4组,每组有3!个permutation。考虑到k为6的结果的第一个位置的值其实还是1,我们可以将k在一开始减1。令i = k/6,我们直接取数组中第i个元素作为第一个位置的结果。故,k变为8,8/6=1,那么第一个位置的值为2,再在数组中将2删掉,那么数组变为[1,3,4]。调整k:k = k - 1 * 6 = 2。重复之前的过程即可。这时,每组的大小为2!,那么k/2 = 2/2 = 1,因此,第二个位置的值为3。将其从数组中删掉,那么数组为[1,4]。调整k:k = k - 1 * 2 = 0。这时,每组的大小为1!,那么k/1 = 0/1 = 0。因此,第三个位置的值为1,将其从数组中删掉。调整k:k = k - 0 * 1 = 0。这时,每组的大小为1,处理同上。
代码
第一种方法
class Solution {
public:
string getPermutation(int n, int k) {
vector<char> sequence(n);
for (int i = 0; i < n; ++i)
sequence[i] = i+ '1';
for (int i = 1; i < k; ++i)
nextPermutation(sequence);
string rs;
for (const auto &ch : sequence)
rs += ch;
return rs;
}
void nextPermutation(vector<char> &sequence) {
int i, j;
for (i = sequence.size() - 2; i >= 0; --i)
if (sequence[i] < sequence[i+1]) break;
for (j = sequence.size() - 1; j > i; --j)
if (sequence[j] > sequence[i]) break;
swap(sequence[i], sequence[j]);
reverse(sequence.begin() + i + 1, sequence.end());
}
};
第二种方法
class Solution {
public:
string getPermutation(int n, int k) {
int divider, i;
vector<char> vec;
string str;
for (int i = 0; i < n; ++i) vec.push_back(i + '1');
--k;
while (n) {
for (i = 1, divider = 1; i < n; ++i)
divider *= i;
i = k / divider;
k -= i * divider;
str += vec[i];
vec.erase(vec.begin() + i);
--n;
}
return str;
}
};