STL中的next_permutation原理以及使用

3 篇文章 0 订阅

一、遇到求下一个全排列的题目

这次通过看题解,了解到的是STL库中又一个强大的函数next_permutation()prev_permutation(),它们所在的头文件为algorithm,其作用是求当前排列的下一个全排列和上一个全排列。

二、实现原理

这里就只说next_permutation()的原理,prev_permutation()的原理和next_permutation相反就行了。
当数组逆序是全排列的最后一个排列,找当前排列的下一个排列就是将原来序列变成逆序的下一步,直到当前序列全部为逆序时,寻找下一个排列将会失败。下面我们用整数类型来解释一下原理:
所以next_permutation的原理是从尾部开始两个相邻的元素数字a和数字b(a在前b在后),满足a < b然后在从尾端找到另一个数字c,满足a < c ,将a 和 c 对调,然后将b及其后面的元素颠倒排序即为求出的下一个序列。
next_permutation的原型如下:

template<class BidirectionalIterator>  
bool next_permutation(  
      BidirectionalIterator _First,   
      BidirectionalIterator _Last  
);  
template<class BidirectionalIterator, class BinaryPredicate>  
bool next_permutation(  
      BidirectionalIterator _First,   
      BidirectionalIterator _Last,  
      BinaryPredicate _Comp  
 );  

cpp实现:

template<class BidirectionalIterator>  
bool next_permutation(  
      BidirectionalIterator first,   
      BidirectionalIterator last  
)  
{  
    if(first == last)  
        return false; //空序列  
  
    BidirectionalIterator i = first;  
    ++i;  
    if(i == last)  
        return false;  //一个元素,没有下一个序列了  
      
    i = last;  
    --i;  
  
    for(;;) {  
        BidirectionalIterator ii = i;  
        --i;  
        if(*i < *ii) {  
            BidirectionalIterator j = lase;  
            while(!(*i < *--j));  
  
            iter_swap(i, j);  
            reverse(ii, last);  
            return true;  
        }  
          
        if(i == first) {  
            reverse(first, last);  //全逆向,即为最小字典序列,如cba变为abc  
            return false;  
        }  
    }   
} 

prev_permutation就是从最尾端开始向前寻找两个相邻的元素,令第一个元素为i,第二个元素为ii,且满足i>ii。然后,从最尾端开始往前寻找第一个小于i的元素,令它为j。然后,将i和j对调,再将ii及其之后的所有元素反转。

三、使用next_permutation()

c语言的使用举栗

#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
    int n;
    while(scanf("%d",&n)&&n){
        int a[1000];
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        do{
            for(int i=0;i<n;i++)
                printf("%d ",a[i]);
            printf("\n");
        }while(next_permutation(a,a+n));
    }
    return 0;
}
输入
3
1 2 3
输出
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值