全排列,即数学中的排列,一个集合中所有可能的排列方式。比如,{1,2,3}的全排列有{1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}六种排列方式。STL中提供了专门的全排列函数,但该函数只能按升序或者降序排列,即字典序。主要有两个函数,next_permutation和prev_permutation。

    头文件:#include <algorithm>

   (1)next_permutation,按照升序进行全排列,参数有两个,需要全排列的数组首地址和数组尾地址。返回类型bool型,成功true,失败false。且该函数自动调换数组中元素位置。比如

#include<bits/stdc++.h>
using namespace std;
int main(){
    int a[3]={1,2,3};
    do{
        cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
    }while(next_permutation(a,a+3));
    return 0;
}

   就可输出{1,2,3}的全部全排列,使用do while原因是为了输出第一次未排列的序列。

   (2)prev_permutation,按照降序进行排列,参数同样也是数组首地址和尾地址,返回类型bool型,成功true,失败false。且自动调换数中元素位置。比如

#include<bits/stdc++.h>
using namespace std;
int main(){
    int a[3]={3,2,1};
    do{
        cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
    }while(prev_permutation(a,a+3));
    return 0;
}

   可以输出{3,2,1}的全排列,使用do while也是为了输出第一次未排列的序列。

   这里需要注意一下,next_permutation只会从当前数组开始进行下一次全排列,而不会从第一全排列开始进行,比如{2,1,3},使用next_permutation不会输出{1,2,3}{1,3,2},而只会从{2,1,3}向后输出,prev_permutation同理。所以某种意义上说,next_permutation是找当前排列方式的下一种排列方式,prev_permutation是寻找当前排列方式的前一种排列方式。所以最好保证数组有序,再使用这两个函数,否则可能会有问题。

   下面看一道例题:

   例题牛客

   基本就是全排列的板子题了,下面看一下代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int i,n;
    cin>>n>>i;
    int a[n];
    for(int q=0;q<n;q++) { cin>>a[q]; }
    for(int q=0;q<i;q++) { next_permutation(a,a+n); }
    for(int q=0;q<n;q++) { cout<<a[q]<<" "; }
    return 0;
}