您的位置:首页 > 编程语言 > C语言/C++

排列和组合简单的递归思路以及C++实现

2017-08-21 23:38 721 查看
本文将讲解如何通过递归的方法实现全排列和组合,会详细讲解递归的思路,最后还会给出c++实现的源码。先前学习数据结构和算法的时候一直没有弄明白它们的递归思路,今日遇到,细一思考,发现并没有之前那么难,于是把码下来,同时记下思路。

排列

先讲排列:比如A B C D 四个字母的全排列就是下面24种

ABCD, ABDC, ACDB, ACBD, ADBC, ADCB, BCDA, BCAD, BDAC, BDCA, BACD, BADC, CDAB, CDBA, CABD, CADB, CBDA, CBAD, DABC, DACB, DBCA, DBAC, DCAB, DCBA


假设所有需要排列的字母有n个(R1,R2...Rn),如果后面(n-1)个字母已经是全排列的了(Rm 表示后面n-1个字母),那么(R0,Rm),(R1,Rm)...(Rn,Rm) 就是全排列的,其中Ri不在Rm中。也就是,先把后面n-1个字母全排列好,再全排列所有n个,如何排列n个呢? 让所有的字母轮流排在第一个的位置一次。这样下去,在全排列好后面n-1个之前,先全排列好后面n-2个、、、直到第n个。这也就是递归思路。

#include <vector>
#include <iostream>

using namespace std;

/*
全排列
*/
class TotalOrdering {
//需要排列的字母
vector<char> letters = { 'A', 'B', 'C', 'D' };
vector<string> result;//保存结果

public:

/*
参数:
start表示需要排列字母中开始的下标,开始的时候为0, 所以,开始的时候需要全排列的字母下标是(0, letters.size()-1)
str表示结果字符串
*/
void order(int start, string str) {
if (start >= letters.size()) {//到达组后一个字母,递归结束
result.push_back(str);
return;
}

for (int i = start; i < letters.size(); ++i) {//让所有的字母放在第一个位置一次
order(start + 1, str + letters[start]);
forward(letters, start);
}
}

//把第一个字符放置到最后的位置,其他字符往前移动一位
//比如开始是abcd, 通过该函数之后变成bcda
void forward(vector<char> &letters, int start) {
if (start >= letters.size() - 1)return;

char first = letters[start];
int i = start + 1;
for (; i < letters.size(); ++i) {
letters[i - 1] = letters[i];
}
letters[i - 1] = first;
}

void print() {
auto begin = result.begin();
for (; begin != result.end(); ++begin) {
string tempStr = *begin;

cout << tempStr.c_str() << ", ";
}
}
};

int main() {
TotalOrdering totalOrdering;
totalOrdering.order(0, "");
totalOrdering.print();

system("pause");
return 0;
}


组合

现在有三个集合{A, B}, {C, D}, {E, F}, 那么三个集合所有元素的组合便是ACE, ACF, ADE, ADF, BCE, BCF, BDE, BDF这八种。如果后面两个集合中的所有元素已经组合完成(这些组合记为R),同时记Ri表示第一个集合中的元素,那么{Ri, R}(其中i属于(1…n))便是所有的组合。也就是{(R1, R), (R2, R)…(R3, R)}是所有的组合。这便是递归思路。根据它实现码出下面代码:

#include <string>
#include <sstream>
#include <queue>

using namespace std;

class Solution0017 {
public:
const string keyboard[10] = { "0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };

//使用递归的方法
vector<string> result;
vector<string> letterCombinations(string digits) {
if (digits == "") return vector<string>();

combine(0, digits, "");
return result;
}

void combine(int size, string & digits, string str) {
if (size >= digits.length()) {
result.push_back(str);
return;
}
string letters = keyboard[digits[size] - '0'];
for (int i = 0; i < letters.length(); ++i) {
//把第一个集合中的元素分别和其他组合结合, 其他组合已经是“组合”
combine(size + 1, digits, str + letters[i]);
}
}

};

int main() {

Solution0017 solution;
//第一个集合为{a,b,c}, 第二个集合为{d,e,f}
vector<string> result = solution.letterCombinations("23");
cout << result.size() << endl;

system("pause");
return 0;
}


这个例子也是leetcode中第17算法题的答案。

欢迎指教!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: