美文网首页工作生活
使用next_permutation解决排列组合问题

使用next_permutation解决排列组合问题

作者: 漫游之光 | 来源:发表于2019-07-10 15:00 被阅读0次

    next_permutation算法

    next_permutation是C++中的一个函数,具体的作用是,对于一个给定的序列,对其重新排列,生成下一个排列,如何序列为最大序列,则将其重排为最小序列。还有一个对应的函数prev_permutation,这个函数是求前一个排列,如果是已经是最小的排列,则将其重排为最大的排列。next_permutation算法的具体步骤为:

    1. 从后向前查找第一个相邻元素对(i,j),并且满足A[i] < A[j]。
    2. 在[j,end)中寻找一个最小的k使其满足A[i]<A[k]。
    3. 将i与k交换。
    4. 逆置[j,end)。

    下面给出一个简单的实现。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    bool nextPermutation(int *begin, int *end){
        int *i,*j,*k,*x;
        for(x = end - 1;x > begin;--x){
            if(*(x-1) < *x ){
                i = x -1;
                j = x;
                break;
            }
        }
        if(x == begin){
            reverse(begin,end);
            return false;
        }   
        for(x=j,k=j;x<end;++x){
            if(*x < *k && *x > *i){
                k = x;
            }
        }
        iter_swap(i,k);
        reverse(j,end);
        return true;
    }
    
    int main(int argc, char const *argv[])
    {
        int arr[] = {1,2,3,4};
        do{
            for_each(arr,arr+4,[](int a)->void{
                cout<<a<<" ";
            });
            cout<<endl;
        }while (nextPermutation(arr,arr + 4));
        return 0;
    }
    
    

    使用next_permutation求全排列

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    int main(int argc, char const *argv[])
    {
        vector<int> v = {1,2,3,4};
        sort(v.begin(),v.end());
        do{
            for_each(v.begin(),v.end(),[](int a)->void{
                cout<<a<<" ";
            });
            cout<<endl;
        }while (next_permutation(v.begin(),v.end()));
        return 0;
    }
    

    使用next_permutation解决组合问题

    这里有一个技巧,就是next_permutation函数支持重复元素,如果要求从n个元素中选择m个,可以对n-m个0和m个1进行全排列,其中,1代表选中,0代表不选中。对应的代码如下。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    int main(int argc, char const *argv[])
    {
        vector<int> v = {1,2,3,4,5};
        int m = 2,n = 5;
        vector<int> choose(n-m,0);
        for(int i=0;i<m;i++){
            choose.push_back(1);
        }
        do{
            for(int i=0;i<choose.size();i++){
                if(choose[i] == 1){
                    cout<<v[i]<<" ";
                }
            }
            cout<<endl;
        }while (next_permutation(choose.begin(),choose.end()));
        return 0;
    }
    

    使用深度优先搜索解决全排列问题

    在没有接触到next_permutation这个函数之前,遇到排列问题我都是使用DFS解决的。

    给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。输入的字符串是排好序的。如输入abc,输出为:abc、acb、bac、bca、cab、cba。这个题目在一开始的时候,我不知道该怎么做,后来看了一个深搜的题目,发现和这个题目,很类似,然后就想到了解法。下面先给出代码:

    #include<iostream>
    #include <cstring>
    using namespace std;
    
    int len;
    char array[10];
    int visited[10];
    char result[10];
    
    void Dfs(int n){
        //如果是终点,直接返回 
        if(n==len+1){
            result[n] = '\0';
            cout<<result<<endl;
            return;
        }
        //找可以踩的点 
        for(int i=0;i<len;i++){
            if(visited[i] == 0){
                visited[i] = 1;
                result[n-1] = array[i];
                Dfs(n+1);//计算后面的全排列 
                visited[i] = 0;//计算完了,算下一个,这里要释放 
            }
        }
    }
    
    int main(){
        cin>>array;
        len = strlen(array);
        memset(visited,0,sizeof(visited));
        Dfs(1);
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:使用next_permutation解决排列组合问题

        本文链接:https://www.haomeiwen.com/subject/megncctx.html