以数字举例:有一个数组A的数为 :1 2 3 4 ,其按字典序列的全排列为:
1 2 3 4
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 4 1
……….
总共有 n!个排列,现在输入一个数K,输出其第K的排列
方法:采用康托编码的思想,其实就是求出每个位置上的数字:第一个位置的数字,第二个位置的数字。。。。
解法:按顺序求出每个位置上的数,这边假设 K=8 ;数组为:1 2 3 4 ,长度为4,位置p代表数组中第P个数:p=k/ (n-1)!
1、求第一个位置上的数,p代表第一个数在数组A中的位置
1) p=8/(4-1)!=8/6=1; ---------->第一个数即 A[1]=2 2) 把 A[1] 从数组A中去掉,剩下的数为:1 3 4 3) k=k%(4-1)!=8%6=2
2、重复 步骤 1 的过程,求第二个位置上的数:
1)此时 k =2,数组A变为:1 3 4,数组的长度为3 2)p=1/(3-1)!=2/2=1; ---------->第二个数即 A[1]=3 3)把A[1]从数组A中去掉,剩下的数为:1 4 4)k=k%(3-1)!=2%2=0
3、求第3个位置上的数,仍然重复步骤1 的过程:
1)此时K=0,循环结束;结束前,我们要把剩下的位置的数进行确定! 其实很简单:无需任何操作,就是将数组A中剩下的元素按逆序输出:此时数组A中剩下的数字为:1、4; 所以结果序列中第三个数 4,第四个数 1
循环结束的条件为:K=0
最后的结果:第 8 个序列是:2 3 4 1
代码:
#include<iostream> #include<vector> #include<algorithm> using namespace std; int getNjiecheng(int n){ int res=1; for(int i=1;i<=n;i++){ res*=i; } return res; } vector<int> getPermutationSequence(int k,vector<int> v){ vector<int> res; int n=v.size(); if(k>getNjiecheng(n))return res; while(k>0){ int j=getNjiecheng(n-1); int p = k/j; k=k%j; if(k==0){ p-=1; res.push_back(v[p]); vector<int>::iterator iter=v.begin()+p; v.erase(iter); reverse(v.begin(),v.end()); for(int i=0;i<v.size();i++) res.push_back(v[i]); return res; } else{ res.push_back(v[p]); vector<int>::iterator iter=v.begin()+p; v.erase(iter); n--; } } } int main(){ vector<int> v; for(int i=1;i<=4;i++) v.push_back(i); vector<int> res=getPermutationSequence(24,v); for(vector<int>::iterator iter=res.begin();iter!=res.end();iter++){ cout<<*iter<<" "; } cout<<endl; return 0; }
如果我们想得到 n!个全排列:只需循环 N! 次,调用getPermutationSequence(25,v);
for(int i=1;i<=N!;i++){ getPermutationSequence(i,v); }
时间: 2024-10-25 05:41:53