全排列_藍橋杯問題+一點對遞歸的看法

給定N個不同字符,將這N個字符全排列,最終的結果將會是N!

如:給定 ABC三個不同的字符,則結果爲:ABCACBBACBCACABCBA一共3!=3*2=6種情況


通過本題進一步學習了Vector的應用,更深入瞭解了遞歸、循環的使用環境。

下面看代碼

import java.util.*;
public class Main1 {
	public static int count;
	public static void f(Vector<Character> sourse,Vector<Character> result){
		//當 sourse的元素全部轉移給result
		if(sourse.size()==0){
			for(int i=0;i<result.size();i++){//打印此時的排列
				System.out.print(result.elementAt(i));
			}
			System.out.println();
			count++;
			return;
		}
		for(int i=0; i<sourse.size(); i++){//循環中套遞歸,確保size() * size()的全排列
			//給目標賦值 sourse[i] --add--> result[]
			result.add(sourse.elementAt(i));//result將sourse的i元素放到自己尾部
			sourse.remove(i);//sourse針對第i個元素操作
			f(sourse,result);	//這裏的遞歸其實就相當於從頭到尾的一次循環
			//不要忘記回溯
			sourse.add(i,result.elementAt(result.size()-1));
			result.remove(result.size()-1);
			
		}
		
	}
	
	public static void main (String[] args) {
    	Scanner scan = new Scanner(System.in);
    	int n = scan.nextInt();
    	//聲明sourse,result兩個Vector型對象數組,對象爲Character,字符型
    	Vector<Character> sourse = new Vector<Character>();
    	Vector<Character> result = new Vector<Character>();
    	//初始化sourse
    	for(int i=0;i<n;i++){
    		sourse.add((char)(i+'A'));
    	}
    	
    	//調用遞歸方法
    	f(sourse,result);
    	//最後打印全排列的個數
    	System.out.println(count);
    }
}

代碼中的遞歸部分使用了回溯,通過同網上相似代碼的學習發現,其實可以不用試探+回溯的這種方法,可以直接再定義個參數,遞歸的時候作爲形參層層傳下去即可。

但是這種方法實際上不如回溯的方法更省內存,要知道,每一次聲明一個Vector變量就佔用了一部分空間,使用回溯的方法可以節約這些內存,但也會容易邏輯搞錯,特別是對於Vector的對象數組,容易操作出錯。

細想,遞歸不就是一層層的向下循環,每層的形參都在方法體中轉化爲實參,這樣看來,遞歸的方法比簡單的for循環所佔用的資源多多了。所以,能用一個for表示的最好還是不要小題大做使用遞歸。下面是沒有使用試探+回溯的代碼部分。


for (int i = 0; i < sourse.size(); i++) {
			Vector<Character>sourse1=new Vector<Character>(sourse);
			Vector<Character>result1=new Vector<Character>(result);
			result1.add(sourse.elementAt(i));
			sourse1.remove(i);
			f(sourse1, result1);
		}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章