0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

解決不重復(fù)序列的全排列問(wèn)題的兩個(gè)方法:遞歸和字典序法

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:未知 ? 作者:易水寒 ? 2018-03-29 11:19 ? 次閱讀

簡(jiǎn)介

給定 {1, 2, 3, , , n},其全排列為 n! 個(gè),這是最基礎(chǔ)的高中組合數(shù)學(xué)知識(shí)。我們以 n=4 為例,其全部排列如下圖(以字典序樹(shù)形式來(lái)呈現(xiàn)):

程序

我們很容易想到用遞歸來(lái)求出它的所有全排列。

仔細(xì)觀察上圖,

以 1 開(kāi)頭,下面跟著 {2, 3, 4} 的全排列;

以 2 開(kāi)頭,下面跟著 {1, 3, 4} 的全排列;

以 3 開(kāi)頭,下面跟著 {1, 2, 4} 的全排列;

以 4 開(kāi)頭,下面跟著 {1, 2, 3} 的全排列。

代碼如下:

/**

*

* author : 劉毅(Limer)

* date : 2017-05-31

* mode : C++

*/

#include

#include

usingnamespacestd;

voidFullPermutation(intarray[],intleft,intright)

{

if(left==right)

{

for(inti=0;i

cout<

cout<

}

else

{

for(inti=left;i<=?right;i++)

{

swap(array[i],array[left]);

FullPermutation(array,left+1,right);

swap(array[i],array[left]);

}

}

}

intmain()

{

intarray[4]={1,2,3,4};

FullPermutation(array,0,3);

return0;

}

運(yùn)行如下:

咦~ 遞歸寫(xiě)出的全排列有點(diǎn)不完美,它并不嚴(yán)格遵循字典序。但是熟悉 C++ 的朋友肯定知道另一種更簡(jiǎn)單,更完美的全排列方法。

定義于文件 內(nèi)的兩個(gè)算法函數(shù):

1、next_permutation,對(duì)于當(dāng)前的排列,如果在字典序中還存在下一個(gè)排列,返回真,并且把當(dāng)前排列調(diào)整為下一個(gè)排列;如果不存在,就把當(dāng)前排列調(diào)整為字典序中的第一個(gè)排列(即遞增排列),返回假。

2、prev_permutation,對(duì)于當(dāng)前的排列,如果在字典序中還存在上一個(gè)排列,返回真,并且把當(dāng)前排列調(diào)整為上一個(gè)排列;如果不存在,就把當(dāng)前排列調(diào)整為字典序中的最后一個(gè)排列(即遞減排列),返回假。

/**

*

* author : 劉毅(Limer)

* date : 2017-05-31

* mode : C++

*/

#include

#include

usingnamespacestd;

voidFullPermutation(intarray[])

{

do

{

for(inti=0;i

cout<

cout<

}while(next_permutation(array,array+4));

}

intmain()

{

intarray[4]={1,2,3,4};

FullPermutation(array);

return0;

}

運(yùn)行截圖省略。輸出結(jié)果正好符合字典序。

那這個(gè) “輪子” 是怎么做的呢?(摘自侯捷的《STL 源碼剖析》)

1、next_permutation,首先,從最尾端開(kāi)始往前尋找兩個(gè)相鄰元素,令第一元素為*i,第二元素為*ii,且滿足*i < *ii,找到這樣一組相鄰元素后,再?gòu)淖钗捕碎_(kāi)始往前檢驗(yàn),找出第一個(gè)大于*i的元素,令為*j,將 i,j 元素對(duì)調(diào),再將 ii 之后的所有元素顛倒排列,此即所求之 “下一個(gè)” 排列組合。

2、prev_permutation,首先,從最尾端開(kāi)始往前尋找兩個(gè)相鄰元素,令第一元素為*i,第二元素為*ii,且滿足*i > *ii,找到這樣一組相鄰元素后,再?gòu)淖钗捕碎_(kāi)始往前檢驗(yàn),找出第一個(gè)小于*i的元素,令為*j,將 i,j 元素對(duì)調(diào),再將 ii 之后的所有元素顛倒排列,此即所求之 “上一個(gè)” 排列組合。

代碼如下:

boolnext_permutation(int*first,int*last)

{

if(first==last)returnfalse;// 空區(qū)間

int*i=first;

++i;

if(i==last)returnfalse;// 只有一個(gè)元素

i=last;

--i;

for(;;)

{

int*ii=i;

--i;

if(*i< *ii)

{

int*j=last;

while(!(*i< *--j))??// 由尾端往前找,直到遇上比 *i 大的元素

;

swap(*i,*j);

reverse(ii,last);

returntrue;

}

}

if(i==first)// 當(dāng)前排列為字典序的最后一個(gè)排列

{

reverse(first,last);// 全部逆向排列,即為升序

returnfalse;

}

}

boolprev_premutation(int*first,int*last)

{

if(first==last)returnfalse;// 空區(qū)間

int*i=first;

++i;

if(i==last)returnfalse;// 只有一個(gè)元素

i=last;

--i;

for(;;)

{

int*ii=i;

--i;

if(*i> *ii)

{

int*j=last;

while(!(*i> *--j))// 由尾端往前找,直到遇上比 *i 大的元素

;

swap(*i,*j);

reverse(ii,last);

returntrue;

}

}

if(i==first)// 當(dāng)前排列為字典序的第一個(gè)排列

{

reverse(first,last);// 全部逆向排列,即為降序

returnfalse;

}

}

結(jié)后語(yǔ)

這篇文章主要介紹了解決不重復(fù)序列的全排列問(wèn)題的兩個(gè)方法:遞歸和字典序法。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 程序
    +關(guān)注

    關(guān)注

    116

    文章

    3756

    瀏覽量

    80751
  • C++
    C++
    +關(guān)注

    關(guān)注

    21

    文章

    2100

    瀏覽量

    73453

原文標(biāo)題:詳解全排列算法

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    決不重復(fù)序列排列問(wèn)題的兩個(gè)方法

    簡(jiǎn)介給定 {1, 2, 3, , , n},其排列為 n! 個(gè),這是最基礎(chǔ)的高中組合數(shù)學(xué)知識(shí)。
    的頭像 發(fā)表于 04-27 09:21 ?1w次閱讀
    解<b class='flag-5'>決不重復(fù)</b><b class='flag-5'>序列</b><b class='flag-5'>全</b><b class='flag-5'>排列</b>問(wèn)題的<b class='flag-5'>兩個(gè)</b><b class='flag-5'>方法</b>

    求產(chǎn)生一個(gè)0~9的隨機(jī)數(shù)組,要求不重復(fù)

    要求產(chǎn)生一個(gè)0~9的隨機(jī)數(shù)組,數(shù)組不重復(fù),產(chǎn)生10個(gè)數(shù)容易,怎么實(shí)現(xiàn)數(shù)字不重復(fù)?求高手!
    發(fā)表于 06-07 13:20

    【我是電子發(fā)燒友】正電流和負(fù)電流和零電流

    保護(hù)誤動(dòng)作,常采用兩個(gè)第一段組成的四段式保護(hù)。靈敏一段是按躲過(guò)被保護(hù)線路末端單相或相接地短路時(shí)出現(xiàn)的最大零電流整定的。其動(dòng)作電流小,保護(hù)范圍大,但在單相故障切除后的非相運(yùn)行狀態(tài)下
    發(fā)表于 06-21 16:18

    一階通濾波器正負(fù)檢測(cè)的原理和仿真

      常用的正負(fù)檢測(cè)有很多種方法,例如帶阻濾波器(BS)、低通濾波器(LPF)、陷波器(NF)、延遲信號(hào)撤銷
    發(fā)表于 01-11 16:25

    python合并字典的 7 種方法

    | 操作符了,只不過(guò)它通常用于對(duì)集合(set)取并集。利用這一點(diǎn),也可以將它用于字典的合并,只不過(guò)得繞個(gè)彎子,有點(diǎn)不好理解。你得先利用 items 方法將 dict 轉(zhuǎn)成 dict_items,再對(duì)這
    發(fā)表于 04-08 15:11

    DNA片段拼接中的預(yù)歸并重復(fù)序列屏蔽方法

    針對(duì)DNA 片段拼接中的重復(fù)序列識(shí)別及屏蔽問(wèn)題,提出一種預(yù)歸并重復(fù)序列屏蔽方法。在片段拼接前通過(guò)掃描子串標(biāo)識(shí)出可能存在重疊關(guān)系的shotgu
    發(fā)表于 03-21 15:47 ?25次下載

    基于斜率故障模型的模擬電路軟故障字典

    提出了一種新的模擬電路故障字典。與傳統(tǒng)方法不同,該方法利用兩個(gè)節(jié)點(diǎn)電壓之間的關(guān)系函數(shù)作為故障特征。對(duì)于線性模擬電路,節(jié)點(diǎn)電壓關(guān)系函數(shù)為一次
    發(fā)表于 05-25 14:46 ?29次下載

    基于電路功能的分區(qū)診斷故障字典

    本文提出了一種基于電路功能分區(qū)診斷并建立直流故障字典,分步實(shí)施故障定位的電路故障診斷方法。該方法是在構(gòu)成整個(gè)直流故障字典時(shí),通過(guò)對(duì)電路的分析并結(jié)合對(duì)故障
    發(fā)表于 08-31 14:35 ?10次下載

    輸電線路相排列方法

    同塔多回輸電線路之問(wèn)存在著復(fù)雜的電磁耦合關(guān)系,當(dāng)其合環(huán)后,各段線路本身的不平衡相互疊加,加劇了環(huán)型電網(wǎng)的三相不平衡性。為了減小環(huán)型電網(wǎng)的三相不平衡性,結(jié)合線路相排列方式進(jìn)行研究。通過(guò)分析環(huán)型電網(wǎng)中
    發(fā)表于 03-29 17:32 ?2次下載
    輸電線路相<b class='flag-5'>序</b><b class='flag-5'>排列</b><b class='flag-5'>方法</b>

    python實(shí)現(xiàn)合并字典方法

    字典對(duì)象內(nèi)置了一個(gè) update 方法,用于把另一個(gè)字典更新到自己身上。
    的頭像 發(fā)表于 04-08 15:11 ?996次閱讀

    永磁同步電動(dòng)機(jī)分?jǐn)?shù)槽集中繞組排列方法分析

    數(shù) 排列 分析 互相驗(yàn)證 ; 提 出 了 應(yīng)用 電 勢(shì)星 形圖 與 循環(huán)數(shù)對(duì)永磁 同
    發(fā)表于 06-20 10:27 ?0次下載

    兩個(gè)LED和兩個(gè)按鈕的使用

    電子發(fā)燒友網(wǎng)站提供《兩個(gè)LED和兩個(gè)按鈕的使用.zip》資料免費(fèi)下載
    發(fā)表于 01-30 16:04 ?1次下載
    <b class='flag-5'>兩個(gè)</b>LED和<b class='flag-5'>兩個(gè)</b>按鈕的使用

    Python序列字典類型介紹

    字典 介紹 字典是“鍵值對(duì)”的無(wú)序可變序列字典中的每個(gè)元素都是一個(gè)“鍵值對(duì)”,包含:“鍵對(duì)象”和“值對(duì)象”。 可以通過(guò)“鍵對(duì)象”實(shí)現(xiàn)快速獲
    的頭像 發(fā)表于 03-08 17:35 ?1272次閱讀
    Python<b class='flag-5'>序列</b>的<b class='flag-5'>字典</b>類型介紹

    如何判定兩個(gè)信號(hào)序列的相似程度?

    在統(tǒng)計(jì)學(xué)中,相關(guān)是描述兩個(gè)隨機(jī)變量序列或二元數(shù)據(jù)之間的統(tǒng)計(jì)關(guān)系,無(wú)論是否具有因果關(guān)系。
    的頭像 發(fā)表于 04-15 09:14 ?7697次閱讀
    如何判定<b class='flag-5'>兩個(gè)</b>信號(hào)<b class='flag-5'>序列</b>的相似程度?

    Python比較兩個(gè)時(shí)間序列在圖形上是否相似

    比較兩個(gè)時(shí)間序列在圖形上是否相似,可以通過(guò)以下方法: 可視化比較:將兩個(gè)時(shí)間序列繪制在同一張圖上,并使用相同的比例和軸標(biāo)簽進(jìn)行比較??梢杂^察
    的頭像 發(fā)表于 10-16 11:33 ?601次閱讀