一、概念
從n個不同元素中任取m(m≤n)個元素,按照一定的順序排列起來,叫做從n個不同元素中取出m個元素的一個排列。當m=n時所有的排列情況叫全排列。如果這組數有n個,那么全排列數為n!個。
比如a,b,c的全排列一共有3!= 6 種 分別是{a, b, c}、{a, c, b}、{b, a, c}、{b, c, a}、{c, a, b}、{c, b, a}。
二、常用操作
1.頭文件
#include <algorithm>
2.使用方法
這里先說兩個概念:“下一個排列組合”和“上一個排列組合”,對序列 {a, b, c},每一個元素都比后面的小,按照字典序列,固定a之后,a比bc都小,c比b大,它的下一個序列即為{a, c, b},而{a, c, b}的上一個序列即為{a, b, c},同理可以推出所有的六個序列為:{a, b, c}、{a, c, b}、{b, a, c}、{b, c, a}、{c, a, b}、{c, b, a},其中{a, b, c}沒有上一個元素,{c, b, a}沒有下一個元素。
1)next_permutation:求下一個排列組合
a.函數模板:next_permutation(arr, arr+size);
b.參數說明:
arr: 數組名
size:數組元素個數
c.函數功能: 返回值為bool類型,當當前序列不存在下一個排列時,函數返回false,否則返回true,排列好的數在數組中存儲
d.注意:在使用前需要對欲排列數組按升序排序,否則只能找出該序列之后的全排列數。
比如,如果數組num初始化為2,3,1,那么輸出就變為了:{2 3 1} {3 1 2} {3 2 1}
2)prev_permutation:求上一個排列組合
a.函數模板:prev_permutation(arr, arr+size);
b.參數說明:
arr: 數組名
size:數組元素個數
c.函數功能: 返回值為bool類型,當當前序列不存在上一個排列時,函數返回false,否則返回true
d.注意:在使用前需要對欲排列數組按降序排序,否則只能找出該序列之后的全排列數。
三、代碼
#include <iostream> #include <algorithm> using namespace std; int main () { int arr[] = {3,2,1}; cout<<"用prev_permutation對3 2 1的全排列"<<endl; do { cout << arr[0] << ' ' << arr[1] << ' ' << arr[2]<<'\n'; } while ( prev_permutation(arr,arr+3) ); ///獲取上一個較大字典序排列,如果3改為2,只對前兩個數全排列 int arr1[] = {1,2,3}; cout<<"用next_permutation對1 2 3的全排列"<<endl; do { cout << arr1[0] << ' ' << arr1[1] << ' ' << arr1[2] <<'\n'; } while ( next_permutation(arr1,arr1+3) ); ///獲取下一個較大字典序排列,如果3改為2,只對前兩個數全排列 ///注意數組順序,必要時要對數組先進行排序 return 0; }
四、全排列遞歸思路

public class hello { public static int arr[] = new int[]{1,2,3}; public static void main(String[] args) { perm(arr,0,arr.length-1); } private static void swap(int i1, int i2) { int temp = arr[i2]; arr[i2] = arr[i1]; arr[i1] = temp; } /** * 對arr數組中的begin~end進行全排列 * * 比如: * arr = {1,2,3} * 第一步:執行 perm({1,2,3},0,2),begin=0,end=2; * j=0,因此執行perm({1,2,3},1,2),begin=1,end=2; * j=1,swap(arr,0,0)-->arr={1,2,3}, perm({1,2,3},2,2),begin=2,end=2; * 因為begin==end,因此輸出數組{1,2,3} * swap(arr,1,1) --> arr={1,2,3}; * j=2,swap(arr,1,2)-->arr={1,3,2}, perm({1,3,2},2,2),begin=2,end=2; * 因為begin==end,因此輸出數組{1,3,2} * swap(arr,2,1) --> arr={1,2,3}; * j=1,swap(arr,0,1) --> arr={2,1,3}, perm({2,1,3},1,2),begin=1,end=2; * j=1,swap(arr,1,1)-->arr={2,1,3} perm({2,1,3},2,2),begin=2,end=2; * 因為begin==end,因此輸出數組{2,1,3} * swap(arr,1,1)--> arr={2,1,3}; * j=2,swap(arr,1,2)后 arr={2,3,1},並執行perm({2,3,1},2,2),begin=2,end=2; * 因為begin==end,因此輸出數組{2,3,1} * swap(arr,2,1) --> arr={2,1,3}; * swap(arr,1,0) --> arr={1,2,3} * j=2,swap(arr,2,0) --> arr={3,2,1},執行perm({3,2,1},1,2),begin=1,end=2; * j=1,swap(arr,1,1) --> arr={3,2,1} , perm({3,2,1},2,2),begin=2,end=2; * 因為begin==end,因此輸出數組{3,2,1} * swap(arr,1,1) --> arr={3,2,1}; * j=2,swap(arr,2,1) --> arr={3,1,2},並執行perm({2,3,1},2,2),begin=2,end=2; * 因為begin==end,因此輸出數組{3,1,2} * swap(arr,2,1) --> arr={3,2,1}; * swap(arr,0,2) --> arr={1,2,3} * */ public static void perm(int arr[], int begin,int end) { if(end==begin){ //一到遞歸的出口就輸出數組,此數組為全排列 for(int i=0;i<=end;i++){ System.out.print(arr[i]+" "); } System.out.println(); return; } else{ for(int j=begin;j<=end;j++){ swap(begin,j); //for循環將begin~end中的每個數放到begin位置中去 perm(arr,begin+1,end); //假設begin位置確定,那么對begin+1~end中的數繼續遞歸 swap(begin,j); //換過去后再還原 } } } }