1. 程式人生 > >一個簡單的全排列演算法

一個簡單的全排列演算法

  • 什麼是全排列?就是從n個數字中選擇n個數字按照一定的順序排列起來。
  • 本文要討論的演算法要完成的任務是:給定一個數組,輸出其所有的全排列結果。要求可以概括為兩點:
  1. 輸出該陣列所有的全排列結果
  2. 任意兩個全排列是不同的,即任意兩個全排列中n個數字排列的順序不能相同
  • 其實核心思想就是列舉陣列中每個位置的數字,而難點就是如何有序地列舉陣列每個位置的數字而做到既全面又不重複。
  • 首先我們以這個陣列為a={1,2,3}為例,要找到它所有的全排列,這裡我們用a[0],a[1],a[2]來表示這個陣列中的第一、第二、第三個位置的數值,當前的陣列各個位置的值為a[0]=1,a[1]=2,a[2]=3。於是演算法可以分為以下幾步來完成:
  1. 對a[0]的位置用1,2,3分別來替換,得到3個子序列
  2. 由於a[0]位置能取的所有的值的情況已經列舉完畢了,所以我們再對這3個子序列中a[1]位置所有能取的值再進行列舉。
  3. 到這裡時,所有的子序列a[0]和a[1]都已經確定了,所以a[2]就自然已經確定了,只需要輸出即可。圖示如下:

其中,用紅色的框標識出來的便是子序列,這裡採用的是遞迴的方法,所以每一層實際上代表著遞迴的深度。

package nextPer;

import java.util.Arrays;

public class NextPer {
	public static void main(String[] args) {
		int[] arr={1,2,3};
		nextPer(arr,0);
	}
	private static void nextPer(int[] arr,int start){
                    //當start==arr.length-1時,說明子序列的長度為1,就不用再往下分子序列了
		if(start==arr.length-1){
			System.out.println(Arrays.toString(arr));
		}
		for(int i=start;i<arr.length;i++){
                        //start代表的是每一個子序列的第一個位置,我們每一層遞迴的任務都只有一個:
                        //列舉該層子序列第一個位置可以取的值
			int temp=arr[start];
			arr[start]=arr[i];
			arr[i]=temp;
			
                        //該層遞迴的子序列第一個位置已經確定了,所以又可以往下再分
			nextPer(arr,start+1);

                        //把第該層子序列第一個位置的值換成另外一個值,所以要交換回來
			temp=arr[start];
			arr[start]=arr[i];
			arr[i]=temp;
		}
	}
}
  • 要明白這個演算法的思想,只需要明白每一層遞迴在做的事:就是在不斷地劃分子序列,直到不能再劃分為止,就可以輸出該陣列的值----即當子序列長度為1時,該子序列就不能再往下劃分了。
  • 在這裡要注意幾點:
  1. 由於遞迴的特性,是層層往下走,只有走到某個分支的末尾(我們叫做遞迴的出口)時才停止,然後再回溯(就是回到上一層),並把上一層的各個分支走完,再逐步往回走,所以結合輸出結果和圖示我們就可以知道,程式實際上在按從左到右一個分支一個分支地來走的。
  2. 這裡的例子目的只是為了說明其演算法思想,所以比較簡單,但是我們的目的是可以對任意長度的陣列進行全排列,只要明白這個演算法的思路,就可以實現。我們暫時不考慮數組裡面元素重複的情況,這其實可以先去重再用這個方法來實現。
  3. 這個例子可以幫我們理解遞迴的思想,但是遞迴的空間開銷較大,所以使用遞迴的時候要注意有出口而且深度不要太深。

相關推薦

一個簡單排列演算法

什麼是全排列?就是從n個數字中選擇n個數字按照一定的順序排列起來。 本文要討論的演算法要完成的任務是:給定一個數組,輸出其所有的全排列結果。要求可以概括為兩點: 輸出該陣列所有的全排列結果 任意兩個全排列是不同的,即任意兩個全排列中n個數字排列的順序不能相同

每天一個演算法排列演算法

全排列演算法:給出一個有n個元素的集合,求出這個集合所有可能的排列。 一、 遞迴的方法 void permutation(char *arr, int k , int m){ if(

一個排列演算法

從1到N,輸出全排列,共N!條。 分析:用N進位制的方法吧。設一個N個單元的陣列,對第一個單元做加一操作,滿N進 一。每加一次一就判斷一下各位陣列單元有無重複,有則再轉回去做加一操作,沒 有則說明得到了一個排列方案。

dfs 排列演算法(含重複元素)

1、數的全排列 求數字 1 ~ n 的全排列,例如 1~3 的全排列,輸出 1 2 3, 1 3 2 , 2 1 3, 2 3 1, 3 1 2, 3 2 1 #include<bits/stdc++.h> using namespace std; #define runfil

演算法基礎】字串的排列演算法

題目描述 輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。 輸入描述 輸入一個字串,長度不超過9(可能有字元重複),字元只包括大小寫字母。 這道題是劍指offfer中一道

排列演算法(使用遞迴)

問題描述    對於任意的n個字母,實現其的全排列,並查詢第m個,其排列形式。我寫的這個程式碼中主要用的遞迴。 程式碼如下 #include<stdio.h>int n,book[10],k;      &nbs

牛客網 之 數列還原(數列的排列演算法

題目描述 牛牛的作業薄上有一個長度為 n 的排列 A,這個排列包含了從1到n的n個數,但是因為一些原因,其中有一些位置(不超過 10 個)看不清了,但是牛牛記得這個數列順序對的數量是 k,順序對是指滿足 i < j 且 A[i] < A[j] 的對

原創非遞迴實現排列演算法

Python語言描述 空間換時間的做法,藉助佇列去實現全排列 # ---------藉助佇列去實現全排列(原創)--------- from copy import copy class Per_node(object): def __init__(self,el

排列演算法遞迴實現

前言: 在一些演算法題當中有時需要進行全排列,是一個比較簡單的遞迴呼叫,在這裡記錄下,以後可以直接拿來使用。 過程: 例如{1,2,3,4,5}: 第一步: {1}和{2,3,4,5}的全排列組合; {2}和{1,3,4,5}的全排列組合; {3}和{2,1,4,5}的全排列組合; …

演算法練習-- C# DFS 排列演算法

void Main() { var r = A(new List<string>(){"a","b","c","d","e","f"}); Console.WriteLine(r.Cou

紫書第七章-----暴力求解法(排列演算法

遞迴求全排列 /* 本程式是遞迴實現全排列演算法。 思想是分別讓誰打頭。以1,2,3,4為例,一共只有4位, 第一位可以分別讓1,2,3,4打頭,以第一位是1為例, 第二位可以分別讓2,3,4打頭,以第二位是2為例,

排列演算法及其C++實現(轉)

第十六章、全排列問題53.字串的排列。題目:輸入一個字串,打印出該字串中字元的所有排列。例如輸入字串abc,則輸出由字元a、b、c 所能排列出來的所有字串abc、acb、bac、bca、cab 和cba。    分析:此題最初整理於去年的微軟面試100題中第53題,第二次整理於微軟、Google等公司非常好的

排列演算法(字典序法、SJT Algorithm 、Heap's Algorithm)

一、字典序法 1) 從序列P的右端開始向左掃描,直至找到第一個比其右邊數字小的數字,即。 2) 從右邊找出所有比大的數中最小的數字,即。 3) 交換與。 4) 將右邊的序列翻轉,即可得到字典序的下一個排列。 5) 重複上面的步驟,直至得到字典序最大的排列,即左邊數字比右邊的

排列演算法c++實現

問題: Given a collection of numbers, return all possible permutations. For example, [1,2,3] have the following permutations: [1,2,3], [1,3

排列演算法思路解析

1.全排列的定義和公式: 從n個數中選取m(m<=n)個數按照一定的順序進行排成一個列,叫作從n個元素中取m個元素的一個排列。由排列的定義,顯然不同的順序是一個不同的排列。從n個元素中取m個元素的所有排列的個數,稱為排列數。從n個元素取出n個元素的一個排

167 請程式設計實現排列演算法

67、請程式設計實現全排列演算法。 全排列演算法有兩個比較常見的實現:遞迴排列和字典序排列。 /* 67、請程式設計實現全排列演算法。 全排列演算法有兩個比較常見的實現:遞迴排列和字典序排列。 (1)遞迴實現 從集合中依次選出每一個元素,作為排列的第一個元素,然後對剩餘的

演算法筆記之 排列演算法 一 遞迴求解

集合R={1,2,3,4}的全排列 可以分解為:1,{2,3,4}的全排列 + 2,{1,3,4}的全排列 + 3,{1,2,4}的全排列 + 4,{1,2,3}的全排列。 繼續分解:{2,3,4} 為 2,{3,4}的全排列,3,{2,4},  4,{2,3}………………

排列演算法【非遞迴活動數實現】

求解一個問題,有很多種演算法/方法,一旦遇到比較有趣的思想/演算法,就忍不住記錄下來。 題:求n=4時的全排列(當n=4時,序列為:{1, 2, 3, 4}) 演算法的思想: 1. 給排列中的每個元素均賦予一個向左或向右的箭頭。 2. 如果元素k的箭頭指

字典序法生成排列演算法的證明

/** * get the next permutation based on dictionary order method * * @param cur * @return next permutation string, or null if cur is the last */

js實現字元排列演算法

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>字元全排列</title> </head> <body>