您的位置:首页 > 产品设计 > UI/UE

LEETCODE60. Permutation Sequence

2017-04-17 16:42 274 查看
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}

其实就是选定第一位数字后,其他剩下的数字进行排列组合,就能求出以该数字打头的所有排列组合。想必已经能发现一些规律了,我们干脆再举一个具体的例子,比如我们现在想要找第14个数,那么由于14 = 6 + 6 + 2。因此第一个数打头的是3,然后再求{1, 2, 4}中第二个排列组合数,答案是"142"。所以最终答案就是"3142"

具体方法是从高位到低位逐位确定,当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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Permutation Sequence