LEETCODE60. Permutation Sequence

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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值