c++笔试准备(二)数组全排的问题
参考:http://blog.csdn.net/hackbuteer1/article/details/7462447
1.递归算法解决数组全排问题
思路:为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。找到这个规律后,递归的代码就很容易写出来了。
对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
//一个数组,输出这个数组的全排列 #include<iostream> using namespace std; void Print(int * Array,int iSize) //输出当前数组 { for(int i=0;i<iSize;i++) cout<<Array[i]; cout<<endl; } //在[nBegin,nEnd)区间中是否有字符与下标为pEnd的字符相等,在该区间内没有元素和nEnd相等,则将*pbegine与pend交换.对于pBegin==pEnd的情况,返回true bool ifchange(int *pBegin,int *pEnd) { int *p; for(p=pBegin;p<pEnd;p++) { if(*p==*pEnd) return false; } return true; } //递归求解 void Permutation(int* array,int* array_t,int &isize,int iSize) //调用时array和array_t是同一个指针。交换array_t中的数就是交换array中的数。array_t只是指向了下一个数 { int i; int *pch; //直接对当前序列的后一个开始递归调用 if(isize==1) { Print(array,iSize); } else{ for(pch=array_t,i=0;i<isize;i++,pch++) //当前数分别和自己及后面的交换 { if(ifchange(array_t,pch)) //只要等待和*array_t交换的值和前面的数有重合的,就不交换。 { swap(*array_t,*pch); isize--; Permutation(array,array_t+1,isize,iSize); isize++; swap(*array_t,*pch); } } } } void main() { int iSize; int * Array; cin>>iSize; Array=new int[iSize]; for(int i=0;i<iSize;i++) cin>>Array[i]; Print(Array,iSize); Permutation(Array,Array,iSize,iSize); //初始情况下array1中没有元素,大小为0 delete [] Array; Array=0; }