全排列就是指n個元素隨機組合,不重復的所有排列方式,如{1,2,3}就有123,132,213,231,312,321一共6種排列方式。
常見的算法實現分為 遞歸 和 非遞歸 ,這里我們用一個例子來輔助說明。{1,2,3,4}
遞歸的實現:遞歸是一種優雅的思想,層層推進。首先,我們知道要實現1,2,3,4的全排列,每個數都會在第1個位置出現,那我們先固定第1位是1,而后我們要做的就是對后面的3位子序列進行全排列,這時固定子序列的第一位為2。 依此類推,直到子序列只剩1位,返回。畫個簡圖幫助理解。
c++實現
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 //打印數組全部元素 6 void prt(int arr[],int end){ 7 for(int i=0;i<=end;++i){ 8 printf("%d",arr[i]); 9 } 10 } 11 12 void perm(int arr[],int begin,int end){ 13 if(begin==end){ 14 prt(arr,end); 15 printf("\n"); 16 return; 17 } 18 for(int i=begin;i<=end;++i){ 19 swap(arr[begin],arr[i]); //交換兩個元素值 20 perm(arr,begin+1,end); 21 swap(arr[begin],arr[i]); 22 } 23 }
非遞歸的實現:這里采用的是字典序的方式生成全排列,1,2,3,4這4個數,組成形如1234,1243等序列,這些序列中1234最小,4321最大,由此我們從1234開始(或者4321也行),尋找第一個比1234大的序列,是1243;再尋找第一個比1243大的序列,是1324........依此類推,求出所有序列。
具體實現:從右向左開始,找到第一個這樣的數A(n-1)<A(n),從A(n)向右找最后一個比A(n-1)大的數A(m),交換A(n-1)和A(m),將A(n)到末尾所有元素逆序。重復上述步驟直到第一個元素。
c++實現:
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 void perm(int arr[],int len){ 6 if(len<2) return; 7 int i,j,temp; 8 do{ 9 //輸出當前序列 10 prt(arr,len-1); 11 printf("\n"); 12 i=j=len-1; 13 //向前查找第一個變小的元素 14 while(i>0&&arr[i]<arr[i-1]) --i; 15 temp=i; 16 if(i==0) break; 17 //先后查找第一個比arr[i-1]大的元素 18 while(temp+1<len&&arr[temp+1]>arr[i-1]) ++temp; 19 swap(arr[i-1],arr[temp]); //交換兩個值 20 reverse(arr+i,arr+len); //逆序 21 }while(true); 22 }