排列组合
题目: 求排列组合
分析:
排列:
字典序法对给定的字符集中的字符规定了一个先后关系,在此基础上按照顺序依次产生每个排列。
[例]字符集{1,2,3},较小的数字较先,这样按字典序生成的全排列是:123,132,213,231,312,321。
生成给定全排列的下一个排列 所谓一个的下一个就是这一个与下一个之间没有字典顺序中相邻的字符串。这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。
算法思想:
设P是[1,n]的一个全排列。P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn , j=max{i|Pi<Pi+1}, k=max{i|Pi>Pj} ,对换Pj,Pk,将Pj+1…Pk-1PjPk+1…Pn翻转, P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一个
例子:839647521的下一个排列.从最右开始,找到第一个比右边小的数字4(因为4<7,而7>5>2>1),再从最右开始,找到4右边比4大的数字5(因为4>2>1而4<5),交换4、5,此时5右边为7421,倒置为1247,即得下一个排列:839651247.用此方法写出全排列的非递归算法如下
组合:
01转换法
本程序的思路是开一个数组,其下标表示1到n个数,数组元素的值为1表示其代表的数被选中,为0则没选中。
首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。
当第一个“1”移动到数组的n-m的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。
代码:
1: #include<iostream>2: #include<vector>3: #include<algorithm>4: #include<bitset>5: #include<cmath>6: #include<cassert>7:8: using namespace std ;9:10: #define BIT_SIZE 10011:12: bool isFinished(const bitset<BIT_SIZE>& mybits,int n)13: {14: bool findFirstSet = false ;15: for(int i=0;i<n;++i){16: if (!findFirstSet && mybits.test(i)){ //find the first 117: findFirstSet = true ;
18: continue ;
19: }20: if (findFirstSet && !mybits.test(i)){ //the follows must be 121: return false ; //if not 1 return false22: }23: }24: return true ;25: }26:27: int findFirst10(const bitset<BIT_SIZE>& mybits,int n)28: {29: for(int i=0;i<n-1;++i){30: if(mybits.test(i) && !mybits.test(i+1)){
31: return i ;
32: }33: }34: return -1 ;
35: }36:37: void exchangeXY(bitset<BIT_SIZE>& mybits, int pos, int n)38: {39: assert(pos+1<n) ;40: mybits.reset(pos) ;41: mybits.set(pos+1) ;42: }43:44: template<class T>45: void setResult(const vector<T>& vec,46: const bitset<BIT_SIZE>& mybits,
47: int n,
48: vector<vector<T> >&ret)49: {50: vector<T> vT ;51: for(int i=0;i<n;++i){52: if (mybits.test(i)){
53: vT.push_back(vec.at(i)) ;54: }55: }56: ret.push_back(vT) ;57: }58:59: void adjustOne2Left(bitset<BIT_SIZE>& mybits,int pos,int n)60: {61: assert(pos<n) ;62: int count = 0 ;
63: for(int i=0;i<pos;++i){64: if (mybits.test(i)){
65: ++count ;66: }67: }68: for(int i=0;i<count;++i){69: mybits.set(i) ;70: }71: for(int i=count;i<pos;++i)72: {73: mybits.reset(i) ;74: }75: }76:77:78: /// brief: C(n,m), combination get m charactors from n
79: template<class T>80: void comb(const vector<T>& vec,int m, vector<vector<T> > &ret)81: {82: assert(vec.size()>0 && vec.size()<=BIT_SIZE && m <= vec.size()) ;83:84: int n = vec.size() ;
85: unsigned long ul = static_cast<unsigned long>(pow(static_cast<double>(2),m) - 1) ;86: bitset<BIT_SIZE> mybits(ul) ;87: int pos = 0 ;
88: print(mybits,vec) ;89: setResult(vec,mybits,n,ret) ;90: while(!isFinished(mybits,n)){
91: pos = findFirst10(mybits,n) ;92: if (-1 == pos){
93: // not find , over , but this is not possible
94: // do nothing
95: cout << "Error: can't be here !" << endl ;
96: }97: exchangeXY(mybits,pos,n) ;98: adjustOne2Left(mybits,pos,n) ;99: print(mybits,vec) ;100: setResult(vec,mybits,n,ret) ;101: }102: }103: /// brief : P(n,m) ,permutation . a method called dict sort
104: /// param : sortedVec : make sure the element in the vector is sorted
105: template<class T>106: void perm(const vector<T>& sortedVec, vector<vector<T> >& ret)107: {108: vector<T> vecTmp(sortedVec.begin(),sortedVec.end()) ;109: int n = vecTmp.size() ;
110: // find the first i which vec[i]<vec[i+1]
111: int i = -1 ;
112: int j = -1 ;
113: int pos = -1 ;
114: i = n-2 ;115: // the first one
116: ret.push_back(vecTmp) ;117: while(true){118: for(i=n-2;i>=0;--i){
119: if(vecTmp.at(i)<vecTmp.at(i+1)){
120: pos = i ;121: break ;
122: }123: }124: if(i<0){ // not find125: return ;
126: }127: // find the first j vec[j] > vec[i]
128: for(j=n-1;j>=0;--j){
129: if (vecTmp.at(j)> vecTmp.at(i)){
130: break ;
131: }132: }133: if (j<0){ // not find134: return ;
135: }136: swap(vecTmp[i],vecTmp[j]) ;137: reverse(vecTmp.begin()+i+1,vecTmp.end()) ;138: ret.push_back(vecTmp) ;139: }140: }141:142: template<class T>143: void perm(vector<T>& vec,int m, vector<vector<T> >& ret)144: {145: vector<vector<T> > retComb ;146: vector<vector<T> > retTmp;147:148: sort(vec.begin(),vec.end()) ;149: comb(vec,m,retComb) ;150: for(int i=0;i<retComb.size();++i){151: retTmp.clear() ;152: perm(retComb.at(i),retTmp) ;153: ret.insert(ret.end(),retTmp.begin(),retTmp.end()) ;154: }155: }156:
测试代码:
1: template<class T>2: void pln(const vector<T>& vec)3: {4: for(int i=0;i<vec.size();++i){5: cout << vec.at(i) << " " ;
6: }7: cout << endl ;8: }9:10: template<class T>11: void print(const bitset<BIT_SIZE>& mybits,const vector<T>& vec)12: {13: /*
14: int n = vec.size() ;15:16: for(int i=0;i<n;++i){17: if (mybits.test(i)){18: cout << "1 " ;19: }else{20: cout << "0 " ;21: }22: }23: cout << endl ;24: for(int i=0;i<n;++i){25: cout << vec.at(i)<< " " ;26: }27: cout << endl ;28:29: for(int i=0;i<n;++i){30: if (mybits.test(i)){31: cout << vec.at(i) << " " ;32: }33: }34: cout << endl ;35: */36: }37: int main()
38: {39: vector<char> vec ;
40: vec.push_back('a') ;41: vec.push_back('b') ;42: vec.push_back('c') ;43: vec.push_back('d') ;44: vec.push_back('f') ;45:46: vector<vector<char> > retPerm;
47: int m = 3 ;
48: perm(vec,m,retPerm) ;49: for(int i=0;i<retPerm.size();++i){50: for(int j=0;j<retPerm[i].size();++j){51: cout << retPerm[i][j] << " " ;
52: }53: cout << endl ;54: }55: }