C++で組み合わせイテレータを実装する方法
ここでは、以下のような操作を持つイテレータクラスを設計することを考えます。
- ソート済みの重複のない小文字英字からなる文字列と、数値
combinationLengthを引数に取るコンストラクタを定義します。 - 辞書順において次の長さ
combinationLengthの組み合わせを返すnext()関数を定義します。 - 次の組み合わせが存在する場合にのみ
trueを返すhasNext()関数を定義します。
使用例
たとえば、次のように入力された場合を考えてみましょう。
CombinationIterator iterator = new CombinationIterator("xyz", 2);
iterator.next(); // "xy" を返す
iterator.hasNext(); // true を返す
iterator.next(); // "xz" を返す
iterator.hasNext(); // true を返す
iterator.next(); // "yz" を返す
iterator.hasNext(); // false を返す解法のアプローチ
この問題を解くためには、以下の手順に従います。
- 文字列型の配列
combとインデックス変数idxを用意します。 makeCombs()メソッドを定義します。このメソッドは、文字列s、整数l、初期値が空の文字列temp、初期値が 0 のstartを受け取ります。処理内容は以下の通りです。tempのサイズがlと等しい場合、tempをcombに追加して処理を終了します。iをstartからsのサイズまでループさせ、makeCombs(s, l, temp + s[i], i + 1)を再帰的に呼び出します。
printVector()メソッドは文字列配列を引数として受け取り、その要素を表示します。- コンストラクタでは、文字列
cと整数clを受け取ります。 makeCombs(c, cl)を呼び出し、idx := 0を設定します。next()メソッドはidxをインクリメントし、comb[idx - 1]を返します。hasNext()メソッドは、idxがcombのサイズと異なる場合にtrueを、そうでなければfalseを返します。
実装例(C++)
理解を深めるために、以下の実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
class CombinationIterator {
public:
vector <string> combs;
int idx;
void makeCombs(string s, int l, string temp ="", int start = 0){
if(temp.size() == l){
combs.push_back(temp);
return;
}
for(int i = start; i < s.size(); i++){
makeCombs(s, l, temp + s[i], i + 1);
}
}
void printVector(vector <string> v){
for(int i = 0; i < v.size(); i++){
cout << v[i] << "\n";
}
cout << endl;
}
CombinationIterator(string c, int cl) {
makeCombs(c, cl);
idx = 0;
}
string next() {
idx++;
return combs[idx - 1];
}
bool hasNext() {
return !(idx == combs.size());
}
};
main(){
CombinationIterator ob("xyz", 2);
cout << (ob.next()) << endl;
cout << (ob.hasNext()) << endl;
cout << (ob.next()) << endl;
cout << (ob.hasNext()) << endl;
cout << (ob.next()) << endl;
cout << (ob.hasNext()) << endl;
}入力
"xyz" と 2 で初期化し、next() と hasNext() を複数回呼び出す
出力
xy 1 xz 1 yz 0
-
C++で実装する二分探索木(BST)イテレータの作り方
二分探索木(BST)に対するイテレータを実装することを考えてみましょう。このイテレータには、次の2つのメソッドが必要です。 next():次の要素(次に小さい値)を返すメソッド hasNext():次の要素が存在するかどうかをブール値で返すメソッド 例えば、以下のような二分探索木があるとします。 この木に対して、関数呼び出しのシーケンスが [next(), next(), hasNext(), next(), hasNext(), next(), hasNext(), next(), hasNext()] である場合、出力は [3, 7, true, 9, true, 15, true,
-
C++で文字列をトークン化(分割)する2つの方法を解説
文字列のトークン化(分割)とは、1つの文字列を区切り文字(スペースやカンマなど)を基準に、複数の部分文字列へ分割する処理のことです。C++では、標準ライブラリだけでもいくつかの方法で実現できます。本記事では、代表的な2つの方法をサンプルコード付きで紹介します。方法1:stringstreamを使って空白で分割する1つ目の方法は、stringstreamを使ってスペースで区切られた単語を順に読み取る方法です。この方法はやや制限がありますが、適切なチェックを加えれば十分に目的を果たすことができます。サンプルコード#include <vector> #include <string