藍橋杯 算法 全排列講解 附模板 讓小學生來都看得懂,看不懂你上門砍我

全排列的概念

全排列是什麼?

直接上百度的定義

全排列的本質

講人話:從一個數組中抽取確定量數量的元素,組成一個新的數組。並根據題中的問題,對新組成的數組進行條件
判斷。是否滿足條件,如果滿足條件,就做出一定的代碼行爲。
僞代碼如下
全排列函數體(){
數組 [] list =現有確定;
	if(滿足條件( list )){
		執行目標函數;
		return ; 這裏必須要加,不加是給自己debug添堵
	}
}
滿足條件(數組[] list){
	條件判斷函數;
}

以上是對某一單一排列做出的條件判斷,而我們的目標是對一個數組,[] list,做出條件判斷。那麼問題就來了,如果枚舉出所有的情況呢?

生成一個數組的所有排列

您看到這篇文章的時候應該已經做過一些題了,可能會感覺到非常困惑,爲啥咱就是看不懂他們寫的代碼?
例如有些大佬,交換一下數組中的元素就形成了排列。有些大佬對元素位置判斷一下就形成了排列。

原理講解

從一個數組中取出N個元素,形成一個新的數組。我們實際是按照N位元素,在N的每一位上,不重複的添加元素,並繼
續向下一位添加。(這裏描述有點問題,自己動腦子想一想,兄弟語文不好)

舉例說明:從[1,2,3]中,抽取兩個2元素,組成全排列。當第一位取1的時候,後面的第二位便無法取1,只能取2或
3

看到這裏,你肯定已經明白了全排列用代碼實現的原理(每一位,在當前位可取的範圍進行枚舉,然後轉移到下一位)
如果當前位枚舉了一個元素,則後面位不可使用。
僞代碼:
[] 當前可選取的情況;
for(int i :當前可選取的情況){
	
	當前位置 =i;0
	//因爲當前位置選取了i,所以要把i從當前可選取的情況中去除掉,以免後面的元素選取
	當前可選取的情況 扣除i;
	進行下一層的枚舉(K+1);  //確定了第K位,我們現在需要枚舉第K+1位
	//當前 層 的所有子情況已經討論完畢,既 ABC ----的情況已經討論完畢,排列將進入ABD----的情況
	//i不會在這一層被選取了,所以要恢復i
	當前可選取的情況增加i;
	
}

另一種方式

從當前層開始for循環,交換數組元素。 原理是利用這樣子交換當前層通樣不會重複,自己去想。
這個其實和上面的方法大同小異,只是代碼寫起來少個兩三排。因爲這個方法沒有保證全排列的有序性(出現順序),
自己想一下[1,2,3]的全排列使用這個方法是什麼樣子的。

模板

遞歸出口什麼的多自己想想,懶得寫了,網課殺我
import java.util.*;

public class 藍橋排列 {
	static char[] list = "LANQIAO".toCharArray();
	static boolean[] vis = new boolean[7];//判斷在當前狀況下,哪一位已經被取了
	static char[] put = new char[7]; //存放每一位的情況
	public static HashSet<String> set = new HashSet<String>();//用於最終的條件判斷

	public static void main(String[] args) {
		dfs(0);
		for(String i:set) {System.out.println(i);}
		System.out.println(set.size());
	}
	//不知道dfs是什麼的朋友自己百度,這個簡單
	public static void dfs(int pos) {
		if(pos==7) {//已經枚舉了所有位(7位),進行條件判斷。並中止
			set.add(new String(put));
			return ;
		}
		for(int i=0;i<vis.length;i++) {
			if(!vis[i]) {
				vis[i]=true;
				put[pos]=list[i];
				dfs(pos+1);
				vis[i]=false;
			}
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章