Pythonで「a」から始まる連続増加部分文字列の最長長さを求めるプログラム
問題の概要
小文字の英字と「?」記号を含む文字列 s が与えられます。各「?」については、削除するか、任意の小文字の英字に置き換えることができます。このとき、「a」で始まる連続して増加する部分文字列(例:"abcdef" のようにアルファベット順に1文字ずつ進む文字列)の最長の長さを求める必要があります。
例えば、入力が s = "vta???defke" の場合、出力は 6 になります。これは、s を "vtabcdefke" に変換できるためです。変換後の文字列には "abcdef" という連続増加部分文字列が含まれており、これが「a」で始まる最長のものとなります。
解法のアプローチ
この問題は、文字列を一度走査しながら状態を管理することで線形時間 O(n) で解くことができます。基本的な考え方は以下の通りです。
- maxlen:これまでに見つかった最長の長さを記録します。
- length:現在構築中の連続増加列の長さを追跡します。
- qmarks:直前までに出現した「?」の個数を数えます。「?」は任意の文字に置き換えられるため、連続増加列を延ばす「橋渡し」として機能します。
具体的な手順は次の通りです。
- maxlen := 0
- length := 0
- qmarks := 0
- s 内の各文字 c について以下を繰り返します。
- c が「?」の場合:
- qmarks := qmarks + 1
- それ以外の場合:
- idx := (c のASCIIコード) − ("a" のASCIIコード)
- length <= idx <= length + qmarks または idx <= qmarks を満たす場合は length := idx + 1、そうでなければ length := 0
- qmarks := 0
- maxlen := max(maxlen, min(length + qmarks, 26))
- c が「?」の場合:
- maxlen を返します。
ポイントの解説
英小文字は26種類しかないため、答えは最大でも26になります。そのため min(length + qmarks, 26) という上限処理が必要です。また、新しい文字 c を処理する際、idx(c のアルファベット上の位置)が現在の length と length + qmarks の範囲内に収まっていれば、「?」を適切な文字に置き換えて連続増加列をつなげられることを意味します。
実装例
理解を深めるために、以下のPythonコードを見てみましょう。
def solve(s):
maxlen = length = qmarks = 0
for c in s:
if c == "?":
qmarks += 1
else:
idx = ord(c) - ord("a")
length = idx + 1 if length <= idx <= length + qmarks or idx <= qmarks else 0
qmarks = 0
maxlen = max(maxlen, min(length + qmarks, 26))
return maxlen
s = "vta???defke"
print(solve(s))入力
"vta???defke"
出力
6
まとめ
このアルゴリズムは文字列を1回だけ走査するため、計算量は O(n)、追加のメモリ使用量は O(1) と非常に効率的です。「?」を柔軟なワイルドカードとして扱い、現在の連続増加列の長さとの整合性を逐次チェックすることで、「a」から始まる最長の連続増加部分文字列を正確に求められます。
-
Pythonで重複要素のない最長の連続部分リストの長さを求めるプログラム
問題の概要数値のリスト nums が与えられたとき、すべての要素が一意(重複なし)であるような最長の連続する部分リストの長さを求めることを考えます。例えば、入力が nums = [6, 2, 4, 6, 3, 4, 5, 2] の場合、出力は 5 になります。これは、重複のない要素からなる最長の部分リストが [6, 3, 4, 5, 2] だからです。解き方:スライディングウィンドウ法この問題は「スライディングウィンドウ(尺取り法)」と呼ばれる手法で効率的に解けます。基本的な考え方は以下の通りです。ウィンドウの左端を指す head を 0 で初期化し、各要素の最後に出現したインデックスを記録す
-
Pythonで最長連続シーケンスの長さを求めるアルゴリズムと実装方法
問題概要ソートされていない数値の配列が与えられたとき、その中から連続する要素で構成される最長シーケンスの長さを見つける問題を考えてみましょう。ここでいう「連続」とは、値が1ずつ増えていく数列(例:4, 5, 6, 7)のことを指します。例えば、入力が nums = [70, 7, 50, 4, 6, 5] の場合、最も長い連続シーケンスは [4, 5, 6, 7] となるため、答えは 4 になります。解法のアプローチこの問題は、以下の手順で効率的に解くことができます。まず、配列をセット(set)に変換して重複を除去します。これにより、要素の存在確認が O(1) で行えるようになります。各要素