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;
}
}