60. Permutation Sequence
内容如下:
已知正整数n的全排列按照字典序:
1 123
2 132
3 213
4 231
5 312
6 321
先给出n和k,即求n全排序的第k个排列
一开始是采用回溯思想(回溯):
string intTosting(vector<int> ss){
string s="";
if(ss.size()<1)return s;
for(int i=0;i<ss.size();i++)s+=(ss[i]+'0');
return s;
}
void helper_per(int n,int& cnt,int k,vector<int> item,string& res){
if(item.size()>=n){cnt++;if(cnt==k)res=intTosting(item);
// for(int i=0;i<n;i++)cout<<item[i]<<" ";cout<<endl;
return;}
for(int i=1;i<=n;i++)
{ int f=1;
for(int j=0;j<item.size();j++)
if(i==item[j])f=0;
if(f){
item.push_back(i);
helper_per(n,cnt,k,item,res);
if(cnt==k)return;
item.pop_back();
}
}
}
string getPermutation(int n,int k){
string res="";
if(n<1||k<1)return res;
vector<int>item;
int cnt=0;
helper_per(n,cnt,k,item,res);
return res;
}
发现LTE超时,故只能重来了。
假设有四位数字{1, 2, 3, 4},那么他们能够产生的排列数是:
- 1 + {2, 3, 4}
- 2 + {1, 3, 4}
- 3 + {1, 2, 4}
- 4 + {1, 2, 3}
具体方法是从高位到低位逐位确定,当n=3时,
建立V数组V={1,2,3}
并建立接阶乘数组Permu={1,1!,2!,3!}
设k为第k个序列,则对应最高位在V数组中的下标是ind=(k-1)/permu[num-1]
k==1,2时,ind==0,最高位为v[ind]==1
k==3,4时,ind==1,最高位为v[ind]==2
k==5,6时,ind==2,最高位为v[ind]==3
然后进行k的更新,k=k-index*permu[num-1],index代表个数,如index=1,代表V[index]=2前面还有一组以1开始一组,每组长即全排列长度permu[num-1],主要需要删除此时V中选中的元素防止对后续产生影响string getPermutation(int n,int k){
string res="";
if(n<1||k<1)return res;
vector<int> permu(n+1,1);
for(int i=1;i<=n;i++)
permu[i]=permu[i-1]*i;//permu[i]=i!
vector<int> v(n);
for(int i=0;i<n;i++)
v[i]=i+1;
int num=n;//下标
while(num){
int t=(k-1)/permu[num-1];
res+=(v[t]+'0');
k=k-t*permu[num-1];
for(int i=t+1;i<n;i++)v[i-1]=v[i];
v.pop_back();
num--;
}
return res;
}