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.
分析:
坦言,此題好難,規律的總結來自網絡!代碼根據大嬸的規律寫的!
原文分析:http://www.cnblogs.com/boring09/p/4253508.html
一個一個模擬肯定要超時,只有生算找規律唄。
比如n=4,k=10,先將n=4的所有排列寫出來:
(1) 1 2 3 4 <--第一個序列2 3 4,順序(2) 1 2 4 3
(3) 1 3 2 4
(4) 1 3 4 2
(5) 1 4 2 3
(6) 1 4 3 2 <--最後個序列4 3 2,逆序
(7) 2 1 3 4
(8) 2 1 4 3
(9) 2 3 1 4
(10) 2 3 4 1 <-- 目標序列
(11) 2 4 1 3
(12) 2 4 3 1
(13) 3 1 2 4
(14) 3 1 4 2
(15) 3 2 1 4
... (省略後面的)
假設k=10最終的結果是ABCD
a)首先確定A。
4!=24,在這4!個組合中,尋找第k=10個的開頭A,可以算出A應該是1~n裏面的第 ceiling{k / 3!}=1.666=2個(ceiling表示取上整),即A=2。最後把2從1~n中刪除,更新k,令k=k%3!=4(在(n-1)!中尋找第4個組合的開頭B)
b)然後確定B。
因爲k=4 > 2!=2,所以可以算出B應該是1~n裏面的第ceiling{k/2!}=2個,因爲2之前被刪掉了,所以現在第2個數字是3,即B=3。最後把3從1~n中刪除,更新k=k%2!=2
c)接着看C。
因爲k=0,說明我們要求的序列肯定是某個序列的結尾處,所以之後的數字依次按照從大到小的方式輸出即可,即C=4。把4從1~n中刪除,繼續。
d)最後看D。
因爲k=0,同上,可得D=1。
給大嬸跪了.........,託大嬸的福,上面思路轉化爲代碼:
class Solution {
public:
string getPermutation(int n, int k) {
string result="";
string numstr(n+1,'*');
for(int i=1;i<=n;i++)
numstr[i]=i+'0';
dfs(result,numstr,n,k);
return result;
}
void dfs(string &result,string &numstr,int n,int curk)
{
if(numstr.size()==1)//snumtr[0]=‘*’,是個無用字符
return;
int n1=factorial(n-1);//求階乘
int kk=ceil(1.0*curk/n1);//向上取餘
if(kk==0)
{
//k=0說明我們要求的序列肯定是某個序列的結尾處
//所以之後的數字依次按照從大到小的方式輸出即可
sort(numstr.begin(),numstr.end());
for(int i=0;i<numstr.size()-1;i++)
result+=numstr[numstr.size()-i-1];
return;
}
result+=numstr[kk];
numstr.erase(numstr.begin()+kk);//剷除
dfs(result,numstr,n-1,curk%n1);
}
//求正整數n的階乘
int factorial(int n)
{
int sum = 1;
for(int j = 2; j <= n; j++)
sum *= j;
return sum;
}
};
附暴力辦法(超時):
class Solution {
public:
void next_permutation(string& nums) {
if(nums.empty() || nums.size()==1)
return;
string::iterator ite1=nums.end()-1;
for(;;)
{
string::iterator ite2=ite1;
ite1--;
if(*ite1 < *ite2)
{
string::iterator itej=nums.end();
while(!(*ite1 < *--itej));
iter_swap(ite1,itej);
reverse(ite2,nums.end());
return;
}
if(ite1==nums.begin())
{
reverse(nums.begin(),nums.end());
return;
}
}
}
string getPermutation(int n, int k) {
string result(n,'0');
for(int i=1;i<=n;i++)
result[i-1]=i+'0';
for(int i=0;i<k-1;i++)//執行k-1次
next_permutation(result);
return result;
}
};
注:本博文爲EbowTang原創,後續可能繼續更新本文。如果轉載,請務必複製本條信息!
原文地址:http://blog.csdn.net/ebowtang/article/details/51648717
原作者博客:http://blog.csdn.net/ebowtang
本博客LeetCode題解索引:http://blog.csdn.net/ebowtang/article/details/50668895