先來復習一下概率論的基礎知識: n 個數,從中取 m 個進行進行排列,有多少中排法。 如果不同位置可以重復: 第 1 個位置有 n 種選法 第 2 個位置有 n 種選法 ...... 第 m 個位置有 n 種選法 根據乘法原理:總共 n**m 種排法 如果不能重復 第 1 個位置有 n 種選法 第 2 個位置有 n-1 種選法 ...... 第 m 個位置有 n-m+1 種選法 根據乘法原理: 總共 n*(n-1)*....*(n-m+1)種排法 全排列就是 n! 種排法 |
如果我們要編程生成所有的排列,基本上都是嵌套循環
假如 list 有 n 個元素,從中選 2 個進行排列,偽代碼基本如下
for i=0 to list.length-1
for j=0 to list.length-1{
//找到一種排列方法
temp=list[i,j]
//根據情況排除重復
..
}
for j=0 to list.length-1{
//找到一種排列方法
temp=list[i,j]
//根據情況排除重復

}
問題是上面的例子,我們知道選 2 個元素排列,所以循環是 2 層。
但是,如果我們求得是 P(list,n),n 并不確定,我們不知道循環是幾層,要想寫一個通用的函數,只能借鑒上面的思想,但是不能使用上面的形式
我的想法是:
1、用一個數組 repeat[] 來保存每層的循環變量:repeat[0] 保存第 0 層循環變量的位置,repeat[1] 保存第 1 層循環變量的位置......repeat[n-1] 保存第 n-1 層循環變量的位置
2、標記當前正在第幾層循環:layer
3、集合長度已知 :size = list.length
4、臨時數組:temp[],長度為 n
3、算法描述如下:
循環體(layer == 0 且 repeat[0]== size 則退出循環)
{
如果(前 n-1 層)
{
取出該層循環變量:pos=repeat[layer]
如果 (pos 到達該層末尾,即 pos==size)
{
temp[layer]=null
repeat[layer]=0//該層循環變量歸零
layer--//回到上一層
continue
}
否則
{
temp[layer]=list[pos]
repeat_count[layer]++//該層循環變量增加1
layer++//層數增加 1
continue
}
否則(在最內層)
{
不停改變 temp 最后一個元素,每改變一次,就得到一種新的組合,該層循環變量增加1
當最內層也到達 List 末尾:將該層循環變量歸零,回到上層
}
}
下面是我用 Python 編寫的 permutation 函數,接受三個參數
第一個參數:如果數字則返回排列數;如果是集合,則返回排列的集合
第二個參數:選幾個數排列,默認全排序
第三個參數:是否允許重復,默認不允許
例子:
print permutation(10),'\n' #全排列數
print permutation(10,2),'\n' #10 選 2 排列數
print permutation(10,duplicate=True),'\n' #允許重復的全排列
li=['a','b','c']
print '全排列:',permutation(li),'\n'
print '選2 :',permutation(li,2),'\n'
print '允許重復 :',permutation(li,duplicate=True),'\n'
print permutation(10,2),'\n' #10 選 2 排列數
print permutation(10,duplicate=True),'\n' #允許重復的全排列
li=['a','b','c']
print '全排列:',permutation(li),'\n'
print '選2 :',permutation(li,2),'\n'
print '允許重復 :',permutation(li,duplicate=True),'\n'
運行結果:

下面給出源代碼:
