知识点之排列组合问题
排列组合问题常常使用回溯算法来解决问题,回溯算法的结构框架如下:

void backtracking(参数)
{
    if(终止条件)
    {
        存放结果;
        return;
    }
    for(选择:本层集合中元素(树中节点孩子的数量就是集合的大小))
    {
        处理节点;
        backtracking(路径,选择列表); //递归
        回溯,撤销处理结果;
    }
}

一 排列问题
对于长度为n的某数据进行排列总共有n!种排列方式(当然如果n个数据中存在一样的数据,那么排列的种类数目就会大大减少了)
使用回溯法,对于一个排列,我们可以将其分为第一个数据和后面的数据两个部分,依次将第一个数据和后面的每个数据进行交换(当然也可以使用一个标记数组),确定了第一个数据后,接着去处理后面部分的数据,其方法和前面是一样的,这是一个递归的过程。具体代码如下:

vector<string> Permutation(string str)
{
    vector<string>ret;
    if (str == "")
        return ret;
    sort(str.begin(), str.end()); //对字符串进行升序排序,这样方便之后对重复的排列进行剪枝操作
    cout << str << endl;
    string tmp = "";
    vector<bool> vis(str.size(), false); //设置访问数组,能保证最后结果的字典序
    PermutationCore(ret, tmp, str, vis);
    return ret;
}

void PermutationCore(vector<string>&ret, string &tmp, string &str, vector<bool> &vis)
{
    if (str.size() == tmp.size())
    {

        ret.push_back(tmp); 
        return;
    }
    for (int i = 0; i < str.size(); ++i)
    {
        if (i > 0 && str[i] == str[i - 1] && !vis[i - 1])
            continue;
        if (!vis[i])
        {
            vis[i] = true; //加入处理
            tmp += str[i];
            PermutationCore(ret, tmp, str, vis);
            vis[i] = false; //回溯,撤销处理结果
            tmp.pop_back();
        }
    }
}

二 组合问题
对于长度为n的某数据进行组合总共有2^n-1种组合方式(当然如果n个数据中存在一样的数据,那么组合的种类数目就会大大减少了)
如果输入的数据长度为n,那么这n个字符能构成长度为1,2,…,n的组合,在求长度为m(1<=m<=n)的组合时,可以把n个字符分成第一个字符和后面的字符两个部分,如果组合里面包含第一个字符,则下一步就是在后面的字符中选取m-1个字符;如果组合里面不包含第一个字符,则下一步就是在后面的字符中选取m个字符。这样就形成了递归的函数调用关系f(m,n)=f(m-1,n-1)+f(m,n-1)。代码如下:

vector<vector<int> > Combination(vector<int>number)
{
    vector<vector<int> >ret;
    if (number.empty()) //数据为空就直接返回
        return ret;
    for (int i = 1; i<=number.size(); ++i) //选择长度为i的组合
    {
        vector<int>tmp; //tmp变量存放长度为i的组合结果
        CombinationCore(ret, number, 0, i, tmp); //每次都从第一个字符开始
    }
    return ret;
}
//下面是套用回溯算法的框架的代码
void CombinationCore(vector<vector<int> > &ret,vector<int> &number, int i, int m, vector<int>&tmp)
{
    if(m==0)
    {
        ret.push_back(tmp);
        return;
    }
    for(int j=i;j<number.size();++j)
    {
        tmp.push_back(number[j]);
        CombinationCore(ret,number,j+1,m-1,tmp);
        tmp.pop_back();
    }
}