• 全排列的实现


    全排列的实现-- 递归

    中心思想: 
    设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}. 
    Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列。 
    (1)当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素; 
    (2)当n>1时,Perm(R)可由(r1)+Perm(R1),(r2)+Perm(R2),…,(rn)+Perm(Rn)构成。

    那么具体程序要怎么实现呢?我们来个实际的例子,假设有一数列1,2,3,4 
    那么1,2,3,4的全排列 
    perm({1,2,3,4})=1perm({2,3,4})+2perm({1,3,4})+3perm({1,2,4})+4perm(1,2,3) 
    那么我们只要将每个数,与第一个数交换不就可以得到下一个序列了。
    比如{1,2,3,4}第一个与第二个数交换,那么不就得到2 {1,3,4}了。

    // 输出n个整数的全排列
    #include<iostream>
    using namespace std;
    void swap(int & a, int & b){
        int tmp;
        tmp = a;
        a = b;
        b = tmp;
    }
    void perm(int list[], int low, int high)
    {
        if (low == high)   //当low == high时,此时list就是其中一个排列,所以输出
        {
            for (int i = 0; i <= high; i++){
                cout << list[i];
            }
            cout << endl;
        }
        else
        {
            for (int i = low; i <= high; i++)   // i 从 low 变化到 high,每个元素与第一个元素交换
            {
                swap(list[low], list[i]);
                perm(list, low + 1, high);  // 交换后,得到子序列,用函数perm得到子序列的全排列
                swap(list[low], list[i]); // z最后将元素交换回来,复原,然后为下一步交换另一个元素做准备
            }
        }
    }
    
    int main(){
        int list[10] = {0,1,2,3,4,5,6,7,8,9};
        perm(list, 0, 2);
        return 0;
    }

     Leetcode 46 Permutations

    Given a collection of distinct numbers, return all possible permutations.

    For example,
    [1,2,3] have the following permutations:

    [
      [1,2,3],
      [1,3,2],
      [2,1,3],
      [2,3,1],
      [3,1,2],
      [3,2,1]
    ]
    /*
    比如  abcde的排列   a-bcde     b-acde   c-abde  d-abce  e-abcd  
                       cb-ade     db-cae....
    
    
    */
    class Solution {
    public:
        void perms(vector<int> nums, int low, int high, vector<vector<int>>& res){
            if (low == high){
                res.push_back(nums);   // 此时为base,这时已经到了排列的最后一个字符,即已经完成了一个全排列,只需将这个排列存入结果 
            }
            else{
                for(int i = low; i <= high; i++){
                    int tmp = nums[i];
                    nums[i] = nums[low];
                    nums[low] = tmp;
                    
                    perms(nums, low + 1, high, res);
                    
                    tmp = nums[i];
                    nums[i] = nums[low];
                    nums[low] = tmp;
                }
            }
        }
        
        vector<vector<int>> permute(vector<int>& nums) {
            vector<vector<int>> res;
            if (nums.size() == 0) return res;
            int len = nums.size();
            perms(nums, 0, len - 1, res);
            return res;
        }
    };

    STL模板实现

    在C++的模板中,有一对专门用于实现数字或字符全排列的模板:next_permutation(_BIter, _BIter)和prev_permutation(_BIter, _BIter)。前者实现向后排列,后者实现向前排列,即前者在原顺序上依次产生较大的排列,后者则相反。 
    举个例子:假设需要产生以“354”为基础的全排列,使用next_permutation(_BIter, _BIter),则下一个排列为“435”,而使用prev_permutation(_BIter, _BIter),则下一个排列为“345”。




    字符串的所有组合:
    思路:假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1
    字符中选取m-1个字符;二是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。

    递归终止条件:1、所需要的剩余字符的数量为0,完成递归,输出当前字符数组。2、已到达字符串末尾,已不可能完成任务,需要结束递归
    //string:要处理的字符指针
          //number:表示倒数第number个字符
          //result:存储已选的字符
    void Combination(char* string, int number, vector<char>& result)
    {
        if(number == 0)                                //终止条件1
        {
            vector<char>::iterator iter = result.begin();
            for(; iter < result.end(); ++ iter)
                printf("%c", *iter);
            printf("
    ");
            return;
        }
     
        if(*string == '')                             //终止条件2
            return;
       
        result.push_back(*string);                     //保存这个字符
        Combination(string + 1, number - 1, result);   //递归处理下一个字符,作为倒数第number-1个
        result.pop_back();                             //弹出这个字符,不保存着个字符
        Combination(string + 1, number, result);       //处理下一个字符,作为倒数第number个
    }
    
    void Combination(char* string)
    {
        if(string == NULL)
            return;
     
        int length = strlen(string);
        vector<char> result;
        for(int i = 1; i <= length; ++ i)
        {
            Combination(string, i, result);
        }
    }
      
          
        由于组合可以是1个字符的组合,2个字符的字符……一直到n个字符的组合,因此在函数void Combination(char* string),
    我们需要一个for循环。另外,我们一个vector来存放选择放进组合里的字符。
    延伸扩展
    leetcode 47
    47. Permutations II
    Medium

    Given a collection of numbers that might contain duplicates, return all possible unique permutations.

    Example:

    Input: [1,1,2]
    Output:
    [
      [1,1,2],
      [1,2,1],
      [2,1,1]
    ]



  • 相关阅读:
    5.7填数字游戏求解
    5.6判断回文数字
    5.5百钱买百鸡问题
    5.4三色球问题
    5.3哥德巴赫猜想的近似证明
    5.2求两个数的最大公约数和最小公倍数
    5.1舍罕王的失算
    4.19递归反向输出字符串
    Elasticsearch 安装
    linux 安装nginx步骤
  • 原文地址:https://www.cnblogs.com/simplepaul/p/7639065.html
Copyright © 2020-2023  润新知