C++でn文字の集合から生成できる長さkのすべての文字列を出力する方法
問題概要
この問題では、文字の集合と正整数 k が与えられます。求められているのは、その集合に含まれる文字だけを使って生成できる、長さ k のすべての文字列を出力することです。
入出力例
Input: set = {'x', 'y', 'z'} , k = 2
Output: xx, xy, xz, yx, yy, yz, zx, zy, zz
解法のアプローチ
この問題を解くには、生成可能なすべての文字列を網羅的に見つける必要があります。
サイズ n の集合から作れる長さ k の文字列の総数は nk 個になります。これは、各文字位置ごとに集合内の任意の文字を選べるためです。
この問題は再帰呼び出しを使うことでシンプルに実装できます。基本的な考え方は次の通りです。
- 空文字列からスタートする
- 現在の文字列の末尾に、集合内の各文字を順に1つずつ追加する
- 文字列の長さが k に達した時点で、その文字列を出力する
C++での実装例
#include <bits/stdc++.h>
using namespace std;
void printKLengthString(char set[], string sequence, int n, int k) {
if (k == 0){
cout<<sequence<<"\t";
return;
}
for (int i = 0; i < n; i++){
string newSequence;
newSequence=sequence+set[i];
printKLengthString(set, newSequence, n, k - 1);
}
}
int main() {
char set[] = {'a', 'b'};
int n = 2;
int k = 3;
printKLengthString(set, "", n, k);
}
出力結果
aaa aab aba abb baa bab bba bbb
処理の流れの解説
上記のコードでは、関数 printKLengthString が再帰的に呼び出されます。引数 k が 0 になったとき、すなわち目的の長さの文字列が完成したタイミングで、その文字列を出力して再帰を終了します。
k がまだ 0 でない場合は、for ループによって集合内の各文字を現在の文字列の末尾に追加し、残りの長さ(k - 1)を指定して自分自身を再度呼び出します。これにより、すべての組み合わせが系統的に探索されます。
例えば、集合 {a, b} から長さ 3 の文字列を生成する場合、23 = 8 通りの組み合わせ(aaa, aab, aba, abb, baa, bab, bba, bbb)が漏れなく出力されます。
計算量について
このアルゴリズムの時間計算量は O(nk) です。生成すべき文字列の総数そのものが nk 個であるため、これは漸近的には最適な計算量と言えます。ただし、k や n が大きくなると組み合わせの数が爆発的に増えるため、実際の利用場面では入力サイズに注意が必要です。
-
C++で葉ノードから距離kにあるすべてのノードを出力する方法
問題概要この問題では、二分木と数値Kが与えられ、葉ノードから距離Kにあるすべてのノードを出力することが求められます。二分木(Binary Tree)とは、各ノードが最大2つの子ノード(1つ・2つ・または0個)を持つ特別な木構造のことです。葉ノード(Leaf Node)とは、二分木の末端に位置するノードを指します。この問題における「葉ノードからの距離」とは、葉ノードよりも上位のレベルに位置するノードを意味します。たとえば、レベル4にある葉ノードから距離2のノードは、レベル2に存在することになります。具体例で理解しよう次の図のような二分木を例に考えてみましょう。K = 2 の場合、出力:6 9解法
-
C++で文字配列から作成できるすべての有効な単語を出力する方法
問題の概要 この問題では、単語の集合と文字の配列が与えられ、その配列に含まれる文字だけを使って作成できる単語をすべて見つけ出します。 入力と出力の例 入力 : words[] : {go , hi , run , on , hog , gone} Char[] : {a , o , h , g} 出力 : go , hog 説明: 与えられた単語の中で、文字配列 {a, o, h, g} のみで構成できるのは「go」と「hog」の2つです。「hi」や「run」などは配列に存在しない文字を含むため、有効な単語として出力されません。 解決アプローチ:トライ(Trie)データ構造 この