python實(shí)現(xiàn)全排列代碼(回溯、深度優(yōu)先搜索)
從n個(gè)不同元素中任取m(m≤n)個(gè)元素,按照一定的順序排列起來,叫做從n個(gè)不同元素中取出m個(gè)元素的一個(gè)排列。當(dāng)m=n時(shí)所有的排列情況叫全排列。
公式:全排列數(shù)f(n)=n!(定義0!=1)
1 遞歸實(shí)現(xiàn)全排列(回溯思想)
1.1 思想
舉個(gè)例子,比如你要對(duì)a,b,c三個(gè)字符進(jìn)行全排列,那么它的全排列有abc,acb,bac,bca,cba,cab這六種可能就是當(dāng)指針指向第一個(gè)元素a時(shí),它可以是其本身a(即和自己進(jìn)行交換),還可以和b,c進(jìn)行交換,故有3種可能,當(dāng)?shù)谝粋€(gè)元素a確定以后,指針移向第二位置,第二個(gè)位置可以和其本身b及其后的元素c進(jìn)行交換,又可以形成兩種排列,當(dāng)指針指向第三個(gè)元素c的時(shí)候,這個(gè)時(shí)候其后沒有元素了,此時(shí),則確定了一組排列,輸出。但是每次輸出后要把數(shù)組恢復(fù)為原來的樣子。
1.2 python實(shí)現(xiàn)
def permutations(arr, position, end): if position == end: print(arr) else: for index in range(position, end): arr[index], arr[position] = arr[position], arr[index] permutations(arr, position + 1, end) arr[index], arr[position] = arr[position], arr[index] # 還原到交換前的狀態(tài),為了進(jìn)行下一次交換 arr = [1, 2, 3, 4] permutations(arr, 0, len(arr))
2 深度優(yōu)先搜索(DFS)實(shí)現(xiàn)全排列
2.1 思想
定義全排列問題:輸入一個(gè)長(zhǎng)度為n的列表arr,輸出arr的全排列。
(1)首先可以確定的是,每一種全排列的結(jié)果中包含的列表長(zhǎng)度均是n。想象面前有n個(gè)空盒子,現(xiàn)在要把這n個(gè)數(shù)放到這些空盒子里去,每個(gè)盒子只能放一個(gè)數(shù)。那么第一個(gè)盒子中可以放的選擇是n種,可以使用一個(gè)循環(huán)來逐個(gè)嘗試。
for index in range(0, len(arr)):
temp[position] = arr[index]
(2)第一個(gè)盒子放完后,就該往第二個(gè)盒子里放了。假設(shè)第一個(gè)盒子里放的是arr的第一個(gè)數(shù),那么第二個(gè)盒子就只能放第2~n個(gè)數(shù)了(不能重復(fù))。為此引入visit列表用來標(biāo)記arr中哪些數(shù)字被使用過了。初始化:
visit = [True, True, True, True]
這樣,當(dāng)?shù)谝粋€(gè)位置已經(jīng)使用過時(shí),就在visit里做標(biāo)記:visit = [False, True, True, True]
因此放第一個(gè)盒子的代碼可以改寫如下:
for index in range(0, len(arr)): if visit[index] == True: temp[position] = arr[index] visit[index] = False
(3)當(dāng)?shù)趉個(gè)盒子處理完畢后,處理下一個(gè)盒子直接調(diào)用dfs(k+1)即可,也就是遞歸調(diào)用。解決了當(dāng)下該如何做,下一步也就知道怎么做了。
(4)遞歸調(diào)用的一定要注意的問題是遞歸調(diào)用的出口,否則循環(huán)調(diào)用下去程序會(huì)崩潰無法運(yùn)行。在這個(gè)問題中什么時(shí)候結(jié)束遞歸調(diào)用呢?答案是當(dāng)這n個(gè)盒子都放滿了,即處理到第n+1個(gè)盒子時(shí)結(jié)束調(diào)用,同時(shí)輸出此時(shí)的排列結(jié)果。
2.2 python實(shí)現(xiàn)
visit = [True, True, True, True] temp = ["" for x in range(0, 4)] def dfs(position): # 遞歸出口 if position == len(arr): print(temp) return # 遞歸主體 for index in range(0, len(arr)): if visit[index] == True: temp[position] = arr[index] visit[index] = False # 試探 dfs(position + 1) visit[index] = True # 回溯。非常重要 arr = [1, 2, 3, 4] dfs(0)
注釋了“非常重要”的語句是不能省略的,省略后僅出現(xiàn)[1, 2, 3, 4]一條結(jié)果。dfs(k+1)前后的兩條語句分別稱之為試探和回溯。
3 combination和permutations函數(shù)的區(qū)別
permutations方法重在排列:
import itertools n=3 a=[str(i) for i in range(n)] s="" s=s.join(a) for i in itertools.permutations(s,n): print (''.join(i)) # 結(jié)果 012 021 102 120 201 210
combinations方法重在組合:
import itertools n=3 a=[str(i) for i in range(n)] s="" s=s.join(a) for i in itertools.combinations(s,n): print (''.join(i)) # 結(jié)果 012
以上這篇python實(shí)現(xiàn)全排列代碼(回溯、深度優(yōu)先搜索)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python?mistune庫靈活的Markdown解析器使用實(shí)例探索
本文將深入介紹Python?Mistune,包括其基本概念、安裝方法、示例代碼以及一些高級(jí)用法,以幫助大家充分利用這一工具來處理Markdown文本2024-01-01Python實(shí)現(xiàn)多圖繪制系統(tǒng)的示例代碼
這篇文章主要為大家詳細(xì)介紹了Python如何實(shí)現(xiàn)制作一個(gè)多圖繪制系統(tǒng),文中的示例代碼簡(jiǎn)潔易懂,具有一定的借鑒價(jià)值,感興趣的小伙伴可以學(xué)習(xí)一下2023-09-09python+pygame實(shí)現(xiàn)坦克大戰(zhàn)
這篇文章主要為大家詳細(xì)介紹了python+pygame實(shí)現(xiàn)坦克大戰(zhàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Python利用PyVista進(jìn)行mesh的色彩映射的實(shí)現(xiàn)
這篇文章主要介紹了Python利用PyVista進(jìn)行mesh的色彩映射的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04python使用Pycharm創(chuàng)建一個(gè)Django項(xiàng)目
這篇文章主要介紹了python使用Pycharm創(chuàng)建一個(gè)Django項(xiàng)目,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03python保留格式匯總各部門excel內(nèi)容的實(shí)現(xiàn)思路
這篇文章主要介紹了python保留格式匯總各部門excel內(nèi)容,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06