運(yùn)用Python遞歸算法實(shí)現(xiàn)風(fēng)神巴巴托斯名字全排列

我們知道,風(fēng)神溫迪的別名除了叫巴巴托斯以外,如果沒(méi)記錯(cuò)的話,還有“巴斯巴托”,“巴托巴斯”等稱(chēng)呼(bushi)。今天心血來(lái)潮,想把她所有四個(gè)字“巴巴托斯”的稱(chēng)呼的排列組合給列舉出來(lái),想到最近在學(xué)Python,因此萌生了用Python寫(xiě)算法實(shí)現(xiàn)這一過(guò)程的想法。

在介紹算法之前,我們先了解全排列這個(gè)概念。從n個(gè)不同元素中任取m(m≤n)個(gè)元素,按照一定的順序排列起來(lái),叫做從n個(gè)不同元素中取出m個(gè)元素的一個(gè)排列。當(dāng)m=n時(shí)所有的排列情況叫全排列。我們小學(xué)二年級(jí)學(xué)過(guò),n個(gè)元素全排列個(gè)數(shù)為n!,拿元素(a, b, c)舉例,它的全排列一共有(a,b,c),?(a,c,b),?(b,a,c),?(b,c,a),?(c,a,b),?(c,b,a)六種情況,具體計(jì)算邏輯可以看作下圖:

我們看圖可知,排列的時(shí)候首先固定第一個(gè)字母,然后再改變后兩個(gè)字母的順序,固定第一個(gè)字母一共有三種情況,每種情況又對(duì)應(yīng)兩個(gè)固定后兩個(gè)字母的情況,因此一共有3*2=6種情況。
如果將n擴(kuò)大為4,以(a,b,c,d)舉例,可以先固定第一個(gè)字母確定大類(lèi),(a,*,*,*),?(b,*,*,*),?(c,*,*,*),?(d,*,*,*),每一類(lèi)的后三個(gè)字母又各自有六種情況,所以一共有4*6=24種情況,也就是4!種。以此類(lèi)推,當(dāng)n逐個(gè)增大時(shí),我們可以找到一個(gè)計(jì)算規(guī)律,那就是,只要會(huì)計(jì)算n-1個(gè)元素,那就很容易算出n個(gè)元素的結(jié)果。那如何計(jì)算n-1個(gè)元素的結(jié)果呢?那就不斷套娃,計(jì)算n-2個(gè)元素的情況,直至n=1。這種以少推多的計(jì)算思想也叫作遞歸算法,用計(jì)算機(jī)可以很方便地實(shí)現(xiàn)它。具體python代碼如下:
這塊代碼的具體含義是,定義這個(gè)遞歸算法排序函數(shù)。具體實(shí)現(xiàn)效果如下圖所示:
可以看出,上述排序函數(shù)成功地將(a,b,c,d)的24種排列都計(jì)算了出來(lái)。那么回到正題,如果我們將巴巴托斯的全排列計(jì)算出來(lái),會(huì)有多少種可能呢?
沒(méi)錯(cuò),還是24種可能。不過(guò)細(xì)心的小伙伴會(huì)發(fā)現(xiàn),里面有好多重復(fù)項(xiàng)。這是因?yàn)椤鞍桶屯兴埂庇袃蓚€(gè)巴,但是程序并沒(méi)有把那兩個(gè)巴看成一個(gè)巴,所以一股腦地輸出了24種情況。那么我們要去重,具體操作也很簡(jiǎn)單,只需下面幾行代碼就可:
具體去重原理是根據(jù)24種情況的舊列表重新構(gòu)造了一個(gè)列表,但是往新列表里面添加元素的時(shí)候檢查里面是否已經(jīng)有某元素,如果沒(méi)有,才會(huì)添加。最后結(jié)果一共有12種情況,也正好是原先的數(shù)量除以“巴巴”的排列數(shù)。
最后將這12種結(jié)果粘貼出來(lái),巴巴托斯,巴巴斯托,巴托巴斯,巴托斯巴,巴斯巴托,巴斯托巴,托巴巴斯,托巴斯巴,托斯巴巴,斯巴巴托,斯巴托巴,斯托巴巴,方便學(xué)習(xí)、交流、整活。不說(shuō)了,去抽溫迪卡池去,愿小保底不歪。

