提起全排列,第一印象是不是大學概率中的排列和組合呢,回頭翻了翻書(怪自己太笨,記不住),才發現全排列是排列的一種。那就先延伸一下排列
和組合
唄。
排列
一般地說,從n個不同元素中,任取m(m≤n)個元素,按照一定的順序排成一列,這就叫做從n個元素中取出m個元素的一個排列。
在排列數公式中,當m=n時,有: 這表明,n個不同元素全部取出來排列的排列數等於自然數1到n的連乘積。n個不同元素,全部取出的一個排列叫做n個不同元素的一個全排列。 自然數1到n的連乘積叫做n的階乘,用n!表示,所以n個不同元素的全排列公式則為: 例如:寫出一個陣列{a,b,c}的全排列。 對於初學者可以先畫下圖來算出: 共6個排列,這個數值6是可以根據乘法原理算出來的。第一次有3種選擇,第二次有2種選擇,第三次就有1種選擇。據此共有N=3 X 2 X 1=6種。先看兩道題,曠視最近筆試考了這麼一道題:
對於這道題你有思路嗎?可以這樣考慮:a) 七人的全排列有A(7,7)=5040種排法,由於A,B是對等的,也就是說A在B的左邊和B在A的左邊的
站法數量是相同的,所以有A(7,7)/2=2520種;
b)把AB當成一個整體,求全排列,就是6! = 720
複製程式碼
演算法實現
public static void perm(int A[], int p, int q){
if(p == q){
// 輸出所有結果
printAll(A, q+1);
}else{
int i;
for(i=p; i<=q; i++){
// 交換
swap(A, p, i);
perm(A, p+1, q);
swap(A, p, i);
}
}
}
}
複製程式碼
演算法講解
這裡的實現使用了遞迴,遞迴需要滿足是三個條件:
- 一個問題的解可以分解為幾個子問題的解;
- 這個問題與分解之後的子問題,除了資料規模不同,求解思路完全一樣;
- 存在遞迴終止條件
我們依次對標,上面對3個字母求全排列對遞迴的使用不太明顯,我們來舉4個數字的例子
通過上述的輸出結果,可以通過debug斷點走一遍,你應該可以理解。其中,第一個swap()是把每個元素都和第一個元素進行交換,第二個swap()方法是將上一次的交換歸為原位置,避免重複。 這裡給大家推薦一個視訊,我的思路基本來自這個 視訊。 具體程式碼請移步到我的github上。