從基礎講全排列(Java實現)

一起的遠方發表於2019-03-29

提起全排列,第一印象是不是大學概率中的排列和組合呢,回頭翻了翻書(怪自己太笨,記不住),才發現全排列是排列的一種。那就先延伸一下排列組合唄。

排列

一般地說,從n個不同元素中,任取m(m≤n)個元素,按照一定的順序排成一列,這就叫做從n個元素中取出m個元素的一個排列。

從基礎講全排列(Java實現)
在排列數公式中,當m=n時,有:
從基礎講全排列(Java實現)
這表明,n個不同元素全部取出來排列的排列數等於自然數1到n的連乘積。n個不同元素,全部取出的一個排列叫做n個不同元素的一個全排列。 自然數1到n的連乘積叫做n的階乘,用n!表示,所以n個不同元素的全排列公式則為:

從基礎講全排列(Java實現)
例如:寫出一個陣列{a,b,c}的全排列。 對於初學者可以先畫下圖來算出:

從基礎講全排列(Java實現)
共6個排列,這個數值6是可以根據乘法原理算出來的。第一次有3種選擇,第二次有2種選擇,第三次就有1種選擇。據此共有N=3 X 2 X 1=6種。

先看兩道題,曠視最近筆試考了這麼一道題:

從基礎講全排列(Java實現)
對於這道題你有思路嗎?可以這樣考慮:

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個數字的例子

從基礎講全排列(Java實現)

通過上述的輸出結果,可以通過debug斷點走一遍,你應該可以理解。其中,第一個swap()是把每個元素都和第一個元素進行交換,第二個swap()方法是將上一次的交換歸為原位置,避免重複。 這裡給大家推薦一個視訊,我的思路基本來自這個 視訊。 具體程式碼請移步到我的github上。

相關文章