全排列問題詳解 遞迴實現

2021-10-22 08:56:50 字數 2096 閱讀 5865

給定乙個正整數n,輸出1~n的全排列

首先,根據遞迴的思想,我們可以把求1~n的全排列這個大問題分解為先固定1,求剩下的n-1個數的全排列,在固定2,固定3……依次類推。而對於剩下的這n-1個數,同樣採用這種方法,取裡面的第乙個數,放到當前排列的第乙個位置,再取第二個數放到第乙個位置……

即:對於1,2,3,4……n,這n個數,分別求

1,2,3,……,n

2,3,……,n

3,……,n……n

4,……,n……n

……n,……,n-1

3,2,……,n

…………

n,1,……,n-1

2,1,3,……,n

3,1,2,……,n

……n,1,2,……,n-1

對於分別以1到n開頭,可以通過交換的思想來實現,在遞迴前先將待排元素與當前排列的第乙個元素進行交換,在遞迴結束時,還應交換回來,如1,2,3,在處理2開頭的排列時,先將2和1交換,將2固定到排列的第乙個位置。得到2,1,3,然後處理1和3。待處理完畢輸出以2開頭的全部排列後,遞迴返回到2,1,3這個狀態,在進行一次交換,將2和1交換回來,得到1,2,3這個原始狀態,在進入下一輪,繼續將3和1交換,得到3,1,2,然後進行同樣的處理。

**實現:
#include

using

namespace std;

void

swap

(int

&a,int

&b)void

perm

(int num,

int n,

int a)

cout << endl;

return;}

for(

int j = num; j <= n;

++j)

}int

main()

perm(1

, n, a)

;return0;

}

輸出如下:

時間複雜度分析

其遞迴方程為:t(n)=nt(n-1)+n,因而其時間複雜度要略高於n!,可近似為n!。

從上面的輸出可以看到,其並未遵從字典序。故可以採用回溯的策略,構建一棵解空間樹 ,進行深度優先搜尋,到達葉子結點時即可構成一組排列(從根到葉子的一組完整路徑)。每向下擴充套件一層,試圖填入乙個數,如果該數已經被其祖先使用過,則不可再使用,應判斷下乙個數,這樣到第n+1層時,表明1到n個數已經全部填入,便可結束本次遞迴過程,並輸出當前排列。並且每當返回上一層後,應將該層所填入的數重新標記為未被使用過。

如圖:

**實現

#include

using

namespace std;

bool flag[10]

=;//標記陣列

int permutation[10]

;//儲存當前排列

void

dfs(

int level,

int n)

cout << endl;

return;}

for(

int j =

1; j <= n;

++j)}}

intmain()

時間複雜度分析
第一層有n種選擇,第二層有n-1種,第三層有n-2種……故時間複雜度為n!。

輸出如下:

遞迴實現全排列問題

有一組數r,需要輸出它的全排列。r的遞迴可定義如下 當個數n為1時,perm r r 其中r是集合r中唯一的元素 當個數n大於1時,perm r 由 r1 perm r1 r2 perm r2 r3 perm r3 rn perm rn 構成 其中ri r 即該集合中減去對應元素 遞迴地把這組數規模...

遞迴實現全排列問題

目錄 描述思路 輸出 正文 描述 問題是有一組數r,需要輸出它的全排列。r的遞迴可定義如下 當個數n為1時,perm 其中r是集合r中唯一的元素 當個數n大於1時,perm 由 r1 perm r1 r2 perm r2 r3 perm r3 rn perm rn 構成 其中ri r 即該集合中減去...

遞迴實現全排列

生成全排列的最簡單的遞迴方法的思想 1.可以把幾個數字分成前半部和最後一位。對於0123這四個數來說,最後一位 紅色字型 所出現的情況只有以下四類 先不管前三個數的排列組合情況 3 2 1 0這樣我們就把四個數字的排列問題,變成了3個 對於上述的每一行來說 2.終結條件是1個數字的排列就是其本身。直...