国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

全排列算法思路解析

2019-11-06 06:39:14
字體:
來源:轉載
供稿:網友

1.全排列的定義和公式:

從n個數中選取m(m<=n)個數按照一定的順序進行排成一個列,叫作從n個元素中取m個元素的一個排列。由排列的定義,顯然不同的順序是一個不同的排列。從n個元素中取m個元素的所有排列的個數,稱為排列數。從n個元素取出n個元素的一個排列,稱為一個全排列。全排列的排列數公式為n!,通過乘法原理可以得到。

2.時間復雜度:

n個數(字符、對象)的全排列一共有n!種,所以全排列算法至少時間O(n!)的。如果要對全排列進行輸出,那么輸出的時間要O(n?n!),因為每一個排列都有n個數據。所以實際上,全排列算法對大型的數據是無法處理的,而一般情況下也不會要求我們去遍歷一個大型數據的全排列。

3.列出全排列的初始思想:

解決一個算法問題,我比較習慣于從基本的想法做起,我們先回顧一下我們自己是如何寫一組數的全排列的:1,3,5,9(為了方便,下面我都用數進行全排列而不是字符)。 【1,3,5,9】(第一個) 首先保持第一個不變,對【3,5,9】進行全排列。 同樣地,我們先保持3不變,對【5,9】進行全排列。 保持5不變,對9對進行全排列,由于9只有一個,它的排列只有一種:9。 接下來5不能以5打頭了,5,9相互交換,得到 【1,3,9,5】 此時5,9的情況都寫完了,不能以3打頭了,得到 1,5,3,9 1,5,9,3 1,9,3,5 1,9,5,3 這樣,我們就得到了1開頭的所有排列,這是我們一般的排列數生成的過程。再接著是以3、5、9打頭,得到全排列。

我們現在做這樣的一個假設,假設給定的一些序列中第一位都不相同,那么就可以認定說這些序列一定不是同一個序列,這是一個很顯然的問題。有了上面的這一條結論,我們就可以同理得到如果在第一位相同,可是第二位不同,那么在這些序列中也一定都不是同一個序列。 那么,這個問題可以這樣來看。對 T=【x1,x2,x3,x4,x5,........xn?1,xn】 我們獲得了在第一個位置上的所有情況之后(注:是所有的情況),對每一種情況,抽去序列T中的第一個位置,那么對于剩下的序列可以看成是一個全新的序列 T1=【x2,x3,x4,x5,........xn?1,xn】 序列T1可以認為是與之前的序列毫無關聯了。同樣的,我們可以對這個T1進行與T相同的操作,直到T中只一個元素為止。這樣我們就獲得了所有的可能性。所以很顯然,這是一個遞歸算法。 第一位的所有情況:無非是將x1與后面的所有數x2,x3,.......xn依次都交換一次

示意圖如下:

這里寫圖片描述


這里寫圖片描述


4.全排列的非去重遞歸算法

算法思路:全排列可以看做固定前i位,對第i+1位之后的再進行全排列,比如固定第一位,后面跟著n-1位的全排列。那么解決n-1位元素的全排列就能解決n位元素的全排列了,這樣的設計很容易就能用遞歸實現。

【附代碼段:】

void permutation1(char* str,int sbegin,int send) //全排列的非去重遞歸算法 { if( sbegin == send) //當 sbegin = send時輸出 { for(int i = 0;i <= send; i++) //輸出一個排列 cout << str[i]; cout << endl; } else { for(int i = sbegin; i <= send; i++) //循環實現交換和sbegin + 1之后的全排列 { swap(str[i],str[sbegin]); //把第i個和第sbegin進行交換 permutation1(str,sbegin + 1,send); swap(str[i],str[sbegin]); //【注1】交換回來 } } }

【注1】swap(str[i],str[sbegin])//交換回來 我們來仔細推敲一下循環體里的代碼,當我們對序列進行交換之后,就將交換后的序列除去第一個元素放入到下一次遞歸中去了,遞歸完成了再進行下一次循環。這是某一次循環程序所做的工作,這里有一個問題,那就是在進入到下一次循環時,序列是被改變了。可是,如果我們要假定第一位的所有可能性的話,那么,就必須是在建立在這些序列的初始狀態一致的情況下,所以每次交換后,要還原,確保初始狀態一致。


上一篇:裝配Bean

下一篇:Redis之緩存機制

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 灵宝市| 应用必备| 上思县| 灵川县| 东莞市| 鱼台县| 赣州市| 台北市| 石阡县| 鸡西市| 桐城市| 潼南县| 黄冈市| 垦利县| 平乡县| 色达县| 闽清县| 辽源市| 和硕县| 巩义市| 拉孜县| 本溪市| 监利县| 邻水| 石景山区| 盐亭县| 康保县| 五台县| 华宁县| 武功县| 扶风县| 玛曲县| 衡阳市| 沂源县| 延边| 彭泽县| 延川县| 应用必备| 左云县| 襄城县| 沭阳县|