package edu.cqu.algorithmTest; import java.util.Scanner; // 全排列,遞歸實現 public class Main8 { public static void main(String[] args) { int[] arr = { 1, 2, 3}; bfs(arr, 0, arr.length - 1); } public static void bfs(int []a,int start,int end) { /* * 遞歸的終點是,我們拿着start去逐個和后面的集合考慮要不要交換: * 當需要交換時,我們交換,start+1 * 當不需要交換時,我們不交換,start還是要加1,因為我們要靠着start進入遞歸的最底層 * 一直start比較到最后了,交不交換都反正都結束了,我們打印處結果。然后返回到遞歸的上一層。 * 在上一層(我們的start后退一步),搜索是否應該和start交換的i也加1了。 * 如處理{1,2,3}全排列 * 相當於在處理完{2,3}的全排列后, * 我們回到上一層,start到了{1},此時需要考慮將{1} 和{2,3}里面交換。i就是去尋找2,3的 * * * */ if(start == a.length) { for(int i:a) { System.out.print(i); } System.out.println(); } for(int i = start;i < a.length;i++) { if(isUnique(a,start,i)) { swap(a,start,i); bfs(a,start+1,i); /* * 為什么要再交換呢? * 你比如還是{1,2,3},我拿着{1}去交換{2,3}中間的{2},交換完成之后, * 顯然成了{2} {1,3} 即2,1,3和2,3,1 * 但是,我還要拿{1}去換{2,3}中的3啊,數組成了[2,1,3][2,3,1]我再拿第一個位置交換第三個位置顯然亂套 * 所以,我們恢復原樣。當遞歸完成,回到上一層的時候,上一層的start,i還在哪給你記着呢,你本來換了哪個數 * 原原本本給換回來。每一層都一樣,所以不會亂。 * * * */ swap(a,start,i); } } } static boolean isUnique(int a[],int start,int end ) { /* * //如果在需要被交換的數a[end]之前出現了和它一樣的數,例如{1}想要交換到{2,3,4}中的4沒有問題, * 換完之后組成新的集合{2,3,1}進行遞歸,遞歸會處理好{2,3,1}的全排列 * 但是如果{1}想要和{4,3,4}中的后面一個4進行交換就需要排除,因為當{1}和第一個4交換,已經將{1,3,4}的全排列 * 結果全部給出了。 * 因此,我們逐個檢查a[end]這個元素之前,有沒有和它 一樣的數 * * * */ for(int i = start ;i < end; i++) { if(a[i] == a[end]) { return false; } } return true; } public static void swap(int []a,int m,int n) { int t = a[m]; a[m] = a[n]; a[n] = t; } }