# Backtracking# Recursion# Permutation

i646 - 排列組合-排列

🔗 前往 ZeroJudge 原題

題目描述

題目要求輸出所有長度為 N 的小寫字母排列,其中 N 的範圍是 1 到 7。排列的元素使用 'a', 'b', 'c' 等小寫字母,並且按照字典順序輸出所有可能的排列。輸入以 N=0 結束。

解題思路

這題可以使用遞迴的 Backtracking 演算法來解決。基本思路是維護一個 used 陣列,記錄每個字母是否已經被使用。遞迴函數 dfs 嘗試在每個位置填入一個尚未使用的字母。當所有位置都填滿時,輸出當前的排列。為了確保輸出按照字典順序,在遞迴過程中,我們按照字母的順序嘗試填入每個位置。

複雜度分析

  • 時間複雜度: O(n!),其中 n 是輸入的整數 N。因為需要生成所有可能的排列,排列的數量是 n!。
  • 空間複雜度: O(n),主要用於儲存 a 陣列和 used 陣列。遞迴深度也是 O(n)。

程式碼

#include <iostream>
using namespace std;
int a[8],n;
bool used[8];
void dfs(int x,int y){
	if(y==n){
		for(int i=0;i<n;++i)
			cout << (char)(a[i]+'a');
		cout << "\n";
		return;
	}
	for(int i=0;i<n;++i)
		if(!used[i]){
			used[i]=1;
			a[y]=i;
			dfs(i+1,y+1);
			used[i]=0;
		}
}
int main(){
	while(cin >> n){
		if(n==0)break;
		for(int i=0;i<n;++i){
			used[i]=1;
			a[0]=i;
			dfs(i+1,1);
			used[i]=0;
		}
	}
}

Discussion