排列和组合简单的递归思路以及C++实现
2017-08-21 23:38
721 查看
本文将讲解如何通过递归的方法实现全排列和组合,会详细讲解递归的思路,最后还会给出c++实现的源码。先前学习数据结构和算法的时候一直没有弄明白它们的递归思路,今日遇到,细一思考,发现并没有之前那么难,于是把码下来,同时记下思路。
假设所有需要排列的字母有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个。这也就是递归思路。
这个例子也是leetcode中第17算法题的答案。
欢迎指教!
排列
先讲排列:比如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算法题的答案。
欢迎指教!
相关文章推荐
- 简单谈谈 C/C++ 递归的思想,实现,以及和循环的关系。
- c++ 递归实现不同字母的全排列组合
- 初学者看过来:简单谈谈 C/C++ 递归的思想,实现,以及和循环的关系
- 初学者看过来:简单谈谈 C/C++ 递归的思想,实现,以及和循环的关系。
- 简单谈谈 C/C++ 递归的思想,实现,以及和循环的关系
- 初学者看过来:简单谈谈 C/C++ 递归的思想,实现,以及和循环的关系。
- UML中定义的关系主要有6种: 依赖、关联、聚合、组合/合成、泛化、实现; 以及对应的C++体现
- 排列组合算法的递归实现
- Java 非递归实现的排列组合中的平均分组问题
- C++实现排列组合
- 递归实现排列组合
- 排列组合的递归实现
- C++实现递归实现数字的组合
- 12个字母任选5个进行排列组合,不可重复 javascript 递归实现
- 迭代与递归(及异同点的简单分析)以及Fibonacci数列的两种实现
- 排列与组合的Java递归实现
- C/C++ 排列组合问题(递归)
- 递归实现数字排列组合
- 排列与组合的Java递归实现 (参考)
- 用递归实现排列组合