C++で文字列内の最後の非繰り返し文字を見つける方法
文字列 str が与えられたとき、その中から最後に出現する非繰り返し文字(重複していない文字)を見つける問題を考えてみましょう。例えば、入力文字列が「programming」の場合、後ろから見て最初に一度しか出現しない文字は「n」となります。もし該当する文字が存在しない場合は、-1 を返します。
解決のアプローチ
この問題は、頻度配列(frequency array)を使うことで効率的に解決できます。手順は以下の通りです。
- まず、各文字の出現回数を記録するための頻度配列を作成します。
- 文字列を先頭から走査し、各文字の出現頻度を配列に格納していきます。
- 次に、文字列を末尾から先頭に向かって走査し直します。
- 各文字について、頻度配列の値が
1であるかどうかを確認します。 1であれば、それが最後の非繰り返し文字なので即座に返します。そうでなければ、前の文字の判定へ進みます。
この方法では、時間計算量は O(n)、空間計算量は O(1)(固定サイズ256の配列を使用)となり、非常に効率的です。
C++での実装例
#include <iostream>
using namespace std;
const int MAX = 256;
static string searchNonrepeatChar(string str) {
int freq[MAX] = {0};
int n = str.length();
// 各文字の出現頻度をカウント
for (int i = 0; i < n; i++)
freq[str.at(i)]++;
// 末尾から走査して最初の非繰り返し文字を探す
for (int i = n - 1; i >= 0; i--) {
char ch = str.at(i);
if (freq[ch] == 1) {
string res;
res += ch;
return res;
}
}
return "-1";
}
int main() {
string str = "programming";
cout << "Last non-repeating character: " << searchNonrepeatChar(str);
}
実行結果
Last non-repeating character: n
コードのポイント
freq[MAX]は ASCII 文字全体(256種類)をカバーできるサイズで宣言しています。- 1回目のループで各文字の出現回数を集計し、2回目のループで末尾から判定を行うことで、「最後の」非繰り返し文字を正確に特定できます。
- 該当する文字が見つからなかった場合は、文字列
"-1"を返す仕様になっています。
-
C++でソート順のN番目のバイナリ文字列を効率的に求める方法
問題概要 この問題では、正の整数Nが与えられます。記号「a」と「b」のみを使用して生成できる無限の文字列リストを辞書順(辞書式順序)に並べたとき、そのN番目の文字列を見つけることが課題です。 文字列のリストは以下のように並んでいます。 a, b, aa, ab, ba, bb, aaa, aab, aba, … 例で問題を理解する 入力:N = 8 出力:aab 解法アプローチ 最も単純な解決策は、ループを使って文字列を先頭から順にすべて生成し、N番目の文字列を返す方法です。この方法でも正しい結果は得られますが、Nが大きな値になる場合には計算コストが膨大になり、効率的な解とは言えません。 そこ
-
C++で文字列の部分文字列の総数を求める方法を解説
この記事では、与えられた文字列から作成できる空でない部分文字列の個数を求める方法について解説します。入力 : string = "moon" 出力 : 10 説明 : 部分文字列は m、o、o、n、mo、oo、on、moo、oon、moon の 10 個です。 入力 : string = "yellow" 出力 : 21解法のアプローチ文字列の長さを n とします。上の例からも分かるように、考えられるすべての部分文字列の個数を求めるには、長さ n、(n-1)、(n-2)、(n-3)、……2、1 の部分文字列の個数を順に加算していく必要があります。部分文