首先,这个组合的顺序与 std::next_permutation
的顺序一致。可以参考 排列组合技术。
但如果这道题,直接使用 std::next_permutation
的话,会 TimeOut.
所以应该直接定位到 k 位置的字符串,而不是将所有组合都迭代一遍。
需要两个索引表:
table
| n | 组合个数 |
|---|---|
| 0 | 1 |
| 1 | 1! |
| 2 | 2! |
| 3 | 3! |
| 4 | 4! |
| 5 | 5! |
| 6 | 6! |
| 7 | 7! |
| 8 | 8! |
| 9 | 9! |
dictionary
1 2 3 4 5 6 7 8 9
那么如果有了 k, 对于长度为 n 的字符串来说,首先要定位的是其开头字符。
int pos = (k-1)/table[n-1];
ret += dict[pos];
出现过的字符,不应再有机会出现,故删除之。并继续查看后面的字符。同时 k 也要减掉之前计算过的 pos.
dict.earse(dict.begin() + pos);
k = k - pos * table[n-1];
#include <string>
using std::string;
#include <numeric>
class Solution {
public:
string getPermutation(int n, int k) {
int table[10] = {1};
for (int i=1; i<=9; ++i)
table[i] = i*table[i-1];
string dict(n, ' '), ret(dict);
std::iota(dict.begin(), dict.end(), '1');
for (int i=0; n>0; --n) {
int pos = (k-1)/table[n-1];
ret[i++] = dict[pos];
dict.erase(dict.begin()+pos);
k = k - pos * table[n-1];
}
return ret;
}
};