最近刷leetcode的時候遇見next permutation這道題,感覺挺有意思的乙個題目,遞迴的方法是較簡單並且容易想到的,在網上搜了其餘的解法,就是std::next_permutation非遞迴解法,但是讓人不是很舒服的就是關於原理的部分,千篇一律的都是摘抄《stl原始碼剖析》,也就是這樣的。
在當前序列中,從尾端往前尋找兩個相鄰元素,前乙個記為*i,後乙個記為*ii,並且滿足*i < *ii。然後再從尾端尋找另乙個元素*j,如果滿足*i < *j,即將第i個元素與第j個元素對調,並將第ii個元素之後(包括ii)的所有元素顛倒排序,即求出下乙個序列了。
想必有點c++功底的人都能看明白原始碼是這麼個意思,但是這能算是原理麼,這至多算是實現吧。相比之下老外就嚴謹多了,我找到了一篇文章,防止丟失,我儲存在這裡。其中資源已經沒了。看了這篇文章之後,我豁然開朗,在佩服老外嚴謹的態度之餘,也把自己的理解紀律下來,希望能夠幫助到一些人。
首先,關於什麼是全排列不做解釋。如果乙個排列為a,下乙個排列為a_next,那麼a_next一定與a有盡可能長的公共字首。
看具體例子,乙個排列為124653,如何找到它的下乙個排列,因為下乙個排列一定與124653有盡可能長的字首,所以,腦洞大開一下,從後面往前看這個序列,如果後面的若干個數字有下乙個排列,問題就得到了解決。
第一步:找最後面1個數字的下乙個全排列。
124653
,顯然最後1個數字3不具有下乙個全排列。
第二步:找最後面2個數字的下乙個全排列。
12465
3,顯然最後2個數字53不具有下乙個全排列。
第三步:找最後面3個數字的下乙個全排列。
124653
,顯然最後3個數字653不具有下乙個全排列。
如果乙個序列是遞減的,那麼它不具有下乙個排列
。第四步:找最後面4個數字的下乙個全排列。
124653
,我們發現顯然最後4個數字4653具有下乙個全排列。因為它不是遞減的,例如6453,5643這些排列都在4653的後面。
我們總結上面的操作,並總結出重複上面操作的兩種終止情況:
1:從後向前比較相鄰的兩個元素,直到前乙個元素小於後乙個元素,停止
2:如果已經沒有了前乙個元素,則說明這個排列是遞減的,所以這個排列是沒有下乙個排列的。
124653這個排列終止情況是上面介紹的第一種,從後向前比較相鄰的2個元素,遇到4<6的情況停止。
並且我們可以知道:
1:124653和它的下乙個排列的公共字首為12(因為4653存在下乙個排列,所以前面的數字12保持不變)
2:4後面的元素是遞減的(上面介紹的終止條件是前乙個元素小於後乙個元素,這裡是4<6)
現在,我們開始考慮如何找到4653的下個排列,首先明確4後面的幾個數字中至少有乙個大於4.
4肯定要和653這3個數字中大於4的數字中(6,5)的某乙個進行交換。這裡就是4要和6,5中的某乙個交換,很明顯要和5交換,如果找到這樣的元素呢,因為我們知道4後面的元素是遞減的,所以在653中從後面往前查詢,找到第乙個大於4的數字,這就是需要和4進行交換的數字。這裡我們找到了5,交換之後得到的臨時序列為5643.,交換後得到的643也是乙個遞減序列。
所以得到的4653的下乙個臨時序列為5643,但是既然前面數字變大了(4
653--->5643),後面的自然要變為公升序才行,變換5643得到5346.
所以124653的下乙個序列為125346.
ok,我的原始碼
stl演算法 next permutation剖析
在標準庫演算法中,next permutation應用在數列操作上比較廣泛.這個函式可以計算一組資料的全排列.但是怎麼用,原理如何,我做了簡單的剖析.首先檢視stl中相關資訊.函式原型 template boolnext permutation bidirectionaliterator first...
演算法 Next Permutation問題》
此問題描述如下 給定乙個陣列,首先從後向前找出最長的遞減序列的前乙個元素,比如陣列中,從後向前最長遞減序列是,這個序列的前乙個元素就是4,然後再遞減序列中找到最後乙個比這個數 4 大的數字 就是5 然後將5與4交換,得到新的陣列,然後將交換過後的遞減序列進行翻轉,最後得到的結果就是。如果陣列單調遞減...
next permutation函式初識
include define max m 10 define max n 10 using namespace std bool used max n int perm max m 生成的n!種排列 void permutation1 int pos,int n 針對perm的第pos個位置,究竟使...