再議「生成全排列演算法」

2021-12-29 22:53:30 字數 1856 閱讀 1151

看了「白話演算法(7) 生成全排列的幾種思路(一)」和「白話演算法(7) 生成全排列的幾種思路(二) 康托展開」。在此,將以前本人推導的全排列演算法介紹一下,和廣大的網友交流一下。

以例子說明,用0、1、2、3,四個數組成全排列。

首先可以知道,這四個數組成的全排列一共有4!=24個。那麼給這24個全排列編號,分別為0、1、2……23。再給定乙個演算法,通過編號計算出乙個全排列。本文的目的就是找到這樣的演算法。

把所有的全排列列舉出來可以發現,0在末位的有6個,1在末位的有6個,等等。

觀察0在末位的六個,分別是

1、2、3、0

1、3、2、0

2、1、3、0

2、3、1、0

3、1、2、0

3、2、1、0

可以看出這6個全排列,除了末位是0外,前面三個數正好是1、2、3的全排列

再觀察1在末位的六個,分別是

0、2、3、1

0、3、2、1

2、0、3、1

2、3、0、1

3、0、2、1

3、2、0、1

也可以看出這6個全排列,除了末位是1外,前面三個數正好是0、2、3的全排列

類似的,末位是2和3的6個全排列,除了末位是一樣的以外,前面三個數正好是剩下的三個數的全排列。

於是該問題就可以用下面的步驟來解決。

1、根據編號確定末位數字

2、確定末位數字後,獲得剩餘的數字

3、對編號適當的處理,得到新的編號

4、問題演化成除了末位數字後,用新的編號和剩餘的數字,計算剩餘數字的全排列。

再用乙個具體的例子來說明。比方說,用編號13來計算0、1、2、3的乙個全排列。

1、先給這4個數字排好序。是0、1、2、3

2、計算[13/3!]+1=3,表示末位數是第3個數。注:[x]表示取x的整數部分。

3、把第3個數和第4個數(未排的最後1個數)交換。此時,數字的順序是0、1、3、2。藍色的表示已經排好。

4、新的編號為13 mod 3!=1

5、計算[1/2!]+1=1,表示末位數是第1個數。

6、把第1個數和第3個數(未排的最後1個數)交換。此時,數字的順序是3、1、0、2。藍色的表示已經排好。

7、新的編號為1 mod 2!=1

8、計算[1/1!]+1=2,表示末位數是第2個數。

9、把第2個數和第2個數(未排的最後1個數)交換。此時,數字的順序是3、1、0、2。藍色的表示已經排好。

10、因為只剩下乙個數,所以編號13對應的全排列就是3、1、0、2

其他的編號計算方法和此一樣。

後面的這個**就是按照上面的演算法得到所有的編號和全排列的關係

a(0)

a(1)

a(2)

a(3)編號1

2300

2130

1231

0232

1031

3204

3120

5320

1623

0172

0318

0231

9302

11003

21111

30212

3102

13301

21403

12151

03216

0132

17120

31821

03192

01320

0213

21102

32201

23

23通過這樣的演算法,通過指定的編號就能算出乙個全排列。

如果要遍歷所有的全排列,則只要遍歷編號就能完成。

如果要隨機獲得乙個全排列,則隨機生成乙個編號,再計算出全排列就可以了。

具體的**在我之前的文章「

深搜練習 生成全排列

0.總結 get to the key point firstly,the article comes from lawsonabs 1.前言 使用dfs 輸出數字n內的全排列。2.思想 2.1 深搜 涉及到這種選數問題,第一想到的應該就是深搜。因為深搜主要就是解決選不選這類問題。那該如何實現呢?根...

深度優先搜尋生成全錯序排列

懷戀啊,記得高中和大一之間的暑假裡剛學c語言時我想寫個24點程式,就搜到了用遞迴實現的這個全錯序程式,當時看了好久才看懂,懷戀懷戀。include include using namespace std define max n 100 bool used max n int perm max n ...

暴力求解法中的列舉排列,生成全排列

對於乙個長度為n陣列長度的陣列 要想列舉它的所有的長度為n的全排列出來。有兩種選擇 乙個是直接列舉,另外乙個是使用遞迴來構造。先說最容易理解的直接列舉。例如當 n 5 的時候,我們生成的排列從小到大有 1234,1243,1324,4321。很容易地,我們可以用4個for迴圈搞定。如下 includ...