解法一:最容易想到的就是求出所有的排列組合結果,然後找到第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);
}
};