簡単な再帰的な考え方とC++の実現を並べて組み合わせる
本稿では,再帰的な方法で全配列と組合せを実現する方法を説明し,再帰的な考え方を詳細に説明し,最後にc++実現のソースコードも与える.以前はデータ構造とアルゴリズムを勉強していたとき、それらの再帰的な考え方が分からなかったが、今日出会って、よく考えてみると、以前ほど難しくないことに気づいたので、コードを下ろして、同時に考えをメモした.
整列
まず配列:例えばA B C Dの4文字の全配列は以下の24種類です
すべての配列が必要なアルファベットがn個(R 1,R 2...Rn)あると仮定し、後(n-1)個のアルファベットがすでに全配列(Rmは後n-1個のアルファベットを表す)であれば(R 0,Rm)、(R 1,Rm)...(Rn,Rm)は全配列であり、RiはRmに含まれない.つまり、まず後ろのn-1文字を全部並べて、それからすべてのn個を並べて、どのようにn個を並べますか?すべてのアルファベットを順番に最初の位置に並べます.このようにして、後n−1個を全配列する前に、後n−2個、、、n個目まで全配列する.これが再帰的な考え方です.
コンポジット
現在、3つの集合{A,B},{C,D},{E,F}があり、3つの集合のすべての要素の組み合わせはACE,ACF,ADE,ADF,BCE,BCF,BDE,BDFの8種類である.後の2つの集合のすべての要素が既に組み合わせられている場合(これらの組合せはRと記す)、同時にRiが最初の集合の要素を表す場合、{Ri,R}(iが(1...nに属する)はすべての組合せである.すなわち{(R 1,R),(R 2,R)…(R 3,R)}はすべての組合せである.これが再帰的な考え方です.これに基づいて、次のコードが実装されます.
この例もleetcodeの17番目のアルゴリズム問題の答えです.
ようこそ!
整列
まず配列:例えばA B C Dの4文字の全配列は以下の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個(R 1,R 2...Rn)あると仮定し、後(n-1)個のアルファベットがすでに全配列(Rmは後n-1個のアルファベットを表す)であれば(R 0,Rm)、(R 1,Rm)...(Rn,Rm)は全配列であり、RiはRmに含まれない.つまり、まず後ろのn-1文字を全部並べて、それからすべてのn個を並べて、どのようにn個を並べますか?すべてのアルファベットを順番に最初の位置に並べます.このようにして、後n−1個を全配列する前に、後n−2個、、、n個目まで全配列する.これが再帰的な考え方です.
#include
#include
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;
}
コンポジット
現在、3つの集合{A,B},{C,D},{E,F}があり、3つの集合のすべての要素の組み合わせはACE,ACF,ADE,ADF,BCE,BCF,BDE,BDFの8種類である.後の2つの集合のすべての要素が既に組み合わせられている場合(これらの組合せはRと記す)、同時にRiが最初の集合の要素を表す場合、{Ri,R}(iが(1...nに属する)はすべての組合せである.すなわち{(R 1,R),(R 2,R)…(R 3,R)}はすべての組合せである.これが再帰的な考え方です.これに基づいて、次のコードが実装されます.
#include
#include
#include
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番目のアルゴリズム問題の答えです.
ようこそ!