解法一:最容易想到的就是求出所有的排列组合结果,然后找到第K个返回。
class Solution {
public:
bool flag[15];
char s[15];
string ans;
int count = 0;
void cal(int n, int index, int k)
{
if(count == k) return;
if(index >= n)
{
count ++ ;
if(count == k) ans = s;
return;
}
for(int i = 1; i <= n; i ++)
{
if(flag[i] == false)
{
s[index] = i + '0';
flag[i] = true;
cal(n, index + 1, k);
flag[i] = false;
}
}
}
string getPermutation(int n, int k) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
memset(flag, 0, sizeof(flag));
memset(s, '\0', sizeof(s));
ans = "";
count = 0;
cal(n, 0, k);
return ans;
}
};
解法二:利用规律,逐个计算出结果中每一位应该是什么数字。假设结果是ans, 明显ans是一个n位的string,我们现在要做的就是把ans的每一位放入正确的字符。
对于ans的第index位,题目给定的求第K个,这时index后面还有 x = n - index - 1位,令 k_small = k / x!(取上整),第index位就应该是 n位数字中没有被选择过的第k_small小的数字, 同时k也需要更新 k -= (k_small - 1) * x! .
class Solution {
public:
bool flag[15];
char s[15];
int f[15];
int find_k_small(int n, int k_small)
{
int count = 0;
for(int i = 1; i <= n; i ++)
{
if(flag[i] == false)
{
count ++ ;
if(count == k_small)
{
flag[i] = true;
return i;
}
}
}
return 0;
}
void cal(int n, int k)
{
int index = 0;
int k_small;
while(index < n)
{
int len = n - index - 1;
k_small = k / f[len];
if(k % f[len] != 0)
{
k_small ++ ;
}
s[index] = find_k_small(n, k_small) + '0';
index ++ ;
k -= (k_small - 1) * f[len];
}
}
string getPermutation(int n, int k) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
memset(flag, 0, sizeof(flag));
memset(s, '\0', sizeof(s));
f[0] = f[1] = 1;
for(int i = 2; i < 10; i ++)
f[i] = i * f[i-1];
cal(n, k);
return string(s);
}
};