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

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

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

解決不重復(fù)序列全排列問題的兩個方法

5RJg_mcuworld ? 來源:互聯(lián)網(wǎng) ? 作者:佚名 ? 2018-04-27 09:21 ? 次閱讀
簡介

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

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

仔細(xì)觀察上圖,

以 1 開頭,下面跟著 {2, 3, 4} 的全排列;

以 2 開頭,下面跟著 {1, 3, 4} 的全排列;

以 3 開頭,下面跟著 {1, 2, 4} 的全排列;

以 4 開頭,下面跟著 {1, 2, 3} 的全排列。

代碼如下:

/**

*

* author : 劉毅(Limer)

* date : 2017-05-31

* mode : C++

*/

#include

#include

usingnamespacestd;

voidFullPermutation(intarray[],intleft,intright)

{

if(left==right)

{

for(inti=0;i4;i++)

cout<array[i]<" ";

cout<endl;

}

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)格遵循字典序。但是熟悉 C++ 的朋友肯定知道另一種更簡單,更完美的全排列方法。

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

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

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

/**

*

* author : 劉毅(Limer)

* date : 2017-05-31

* mode : C++

*/

#include

#include

usingnamespacestd;

voidFullPermutation(intarray[])

{

do

{

for(inti=0;i4;i++)

cout<array[i]<" ";

cout<endl;

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

}

intmain()

{

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

FullPermutation(array);

return0;

}

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

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

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

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

代碼如下:

boolnext_permutation(int*first,int*last)

{

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

int*i=first;

++i;

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

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)前排列為字典序的最后一個排列

{

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

returnfalse;

}

}

boolprev_premutation(int*first,int*last)

{

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

int*i=first;

++i;

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

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)前排列為字典序的第一個排列

{

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

returnfalse;

}

}

結(jié)后語

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

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

    關(guān)注

    5054

    文章

    18917

    瀏覽量

    301020

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

文章出處:【微信號:mcuworld,微信公眾號:嵌入式資訊精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    我求解兩個隨機(jī)序列的相干函數(shù)時,得出的相干函數(shù)值總是1

    各位好,有小問題,我求解兩個隨機(jī)序列的相干函數(shù)時,得出的相干函數(shù)值總是1,我是按教程上的函數(shù)求解的,不知道哪里出錯了。
    發(fā)表于 01-08 15:27

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

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

    生成不重復(fù)的隨機(jī)數(shù)

    要求是: 考場座位共7行5列,每次隨機(jī)選一座位,不重復(fù),直至座位選完;我的思路是用一向量[34:0]seat儲存座位使用情況,每次產(chǎn)生座位后,再和seat比較。但怎么讓判斷之后重新產(chǎn)生的座位再比較
    發(fā)表于 06-13 23:53

    藍(lán)牙模塊MAC地址,怎么確保每一模塊的MAC地址不重復(fù)

    藍(lán)牙模塊MAC地址,怎么確保每一模塊的MAC地址不重復(fù),有沒有測試方案?
    發(fā)表于 06-24 17:07

    用于配置兩個QSPI將序列數(shù)據(jù)比特傳輸?shù)狡渌O(shè)備

    : NuMaker-M483KKG V1.1 此示例代碼用于配置兩個 QSPI 將序列數(shù)據(jù)比特傳輸?shù)狡渌O(shè)備。 通過 2 位傳輸模式, 兩個 QSPI 同時傳輸 4
    發(fā)表于 08-29 06:38

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

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

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

    這篇文章主要介紹了解決不重復(fù)序列排列問題的兩個方法:遞歸和字典序法。
    的頭像 發(fā)表于 03-29 11:19 ?6441次閱讀
    解<b class='flag-5'>決不重復(fù)</b><b class='flag-5'>序列</b>的<b class='flag-5'>全</b><b class='flag-5'>排列</b>問題的<b class='flag-5'>兩個</b><b class='flag-5'>方法</b>:遞歸和字典序法

    語音識別的兩個方法_語音識別的應(yīng)用有哪些

    本文主要闡述了語音識別的兩個方法及語音識別的應(yīng)用。
    發(fā)表于 04-01 09:04 ?5917次閱讀

    干貨:兩個關(guān)于Vim的使用問題及小技巧

    最近在使用 VIM 時遇到兩個新的問題,覺得還很挺有價值的?,F(xiàn)在將處理方法總結(jié)后,分享給大家。
    的頭像 發(fā)表于 08-31 12:09 ?2879次閱讀
    干貨:<b class='flag-5'>兩個</b>關(guān)于Vim的使用問題及小技巧

    DS18B20 穩(wěn)定搜索20ROM,不重復(fù),不掉線

    DS18B20 穩(wěn)定搜索20ROM,不重復(fù),不掉線源程序COPY地 再次感謝 sandeepin 作者h(yuǎn)ttps://blog.csdn.net/sandeepin/article
    發(fā)表于 01-17 09:49 ?6次下載
    DS18B20 穩(wěn)定搜索20<b class='flag-5'>個</b>ROM,<b class='flag-5'>不重復(fù)</b>,不掉線

    python集合是什么

    python集合 集合(英文名 set),它是一無序的不重復(fù)元素序列。 這里面有兩個重點: 無序, 不重復(fù) 1. 創(chuàng)建集合 集合的創(chuàng)建有
    的頭像 發(fā)表于 02-23 17:01 ?2201次閱讀

    重復(fù)值處理的常用方法

    重復(fù)值處理主要涉及兩個部分,一是找出重復(fù)值,第二是刪除重復(fù)值,也就是根據(jù)自己設(shè)定的條件進(jìn)行刪
    的頭像 發(fā)表于 03-16 13:55 ?4184次閱讀

    兩個LED和兩個按鈕的使用

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

    如何判定兩個信號序列的相似程度?

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

    Python比較兩個時間序列在圖形上是否相似

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