給定乙個正整數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個數字的排列就是其本身。直...