Pythonで文字列内の英字のみを反転する方法
文字列 S が与えられたとき、英字(アルファベット)だけの位置を反転させ、記号や数字などの英字以外の文字は元の位置にそのまま残すという問題を考えてみましょう。
たとえば、入力文字列が "a-bC-dEf-ghIj" の場合、出力は "j-Ih-gfE-dCba" となります。ハイフン「-」の位置は変わらず、英字部分だけが逆順に入れ替わっているのがポイントです。
解決のアプローチ
この問題は、いわゆる2ポインタ法(two-pointer technique)を使うことで効率的に解けます。先頭から走査するインデックスと、末尾から走査するインデックスの2つを用意し、両側の文字がどちらも英字であれば入れ替える、という流れです。
具体的な手順は以下の通りです。
Sが空文字列の場合は、そのままSを返す。- 結果を格納する文字列
str_を空で初期化し、index1 = 0(先頭側)、index2 = len(S) - 1(末尾側)とする。 index1 < len(S)の間、以下を繰り返す。index2 >= 0かつS[index1]とS[index2]の両方が英字の場合:str_にS[index2]を追加し、index2を1減らしてindex1を1増やす。S[index1]が英字だがS[index2]が英字でない場合:index2を1減らす(対応する英字を探す)。S[index1]が英字でない場合:str_にS[index1]をそのまま追加し、index1を1増やす。- 上記以外の場合:
index2を1減らし、index1を1増やす。
- ループ終了後、
str_を返す。
なお、文字が英字かどうかの判定には、Python標準の文字列メソッド isalpha() を利用します。正規表現モジュール re を使う方法もありますが、isalpha() の方がシンプルで読みやすい実装になります。
実装例
それでは、実際のPythonコードを見てみましょう。
class Solution:
def reverseOnlyLetters(self, S):
if not S:
return S
str_ = ""
index1 = 0
index2 = len(S) - 1
while index1 < len(S):
if index2 >= 0 and S[index1].isalpha() and S[index2].isalpha():
str_ += S[index2]
index2 -= 1
index1 += 1
elif S[index1].isalpha():
index2 -= 1
elif not S[index1].isalpha():
str_ += S[index1]
index1 += 1
else:
index2 -= 1
index1 += 1
return str_
ob1 = Solution()
print(ob1.reverseOnlyLetters("a-bC-dEf-ghIj"))
入力
"a-bC-dEf-ghIj"
出力
"j-Ih-gfE-dCba"
処理の流れと計算量
このアルゴリズムでは、先頭ポインタ index1 が文字列を左から右へ進みながら、末尾ポインタ index2 が右から左へ英字を探します。両者が英字同士で出会ったタイミングで値を交換するイメージです。英字以外の文字は判定された時点でそのまま出力に追加されるため、位置が保持されます。
計算量について見てみると、各文字は高々数回しか参照されないため、時間計算量は O(N)(Nは文字列の長さ)、追加のデータ構造として結果文字列が必要になるため、空間計算量も O(N) となります。
この手法は、リートコード(LeetCode)の「Reverse Only Letters(英字のみを反転)」問題などでも使われる定番テクニックなので、ぜひマスターしておきましょう。
-
Pythonで文字列が大文字のみで構成されているか確認する方法
Pythonでは、文字列が大文字のみで構成されているかどうかを確認する方法は主に2つあります。1つ目は組み込みメソッド isupper() を使う方法、2つ目は正規表現(regex)を使う方法です。 方法1:isupper() メソッドを使う isupper() は、文字列内のすべての英字が大文字であり、かつ少なくとも1つの英字が含まれている場合に True を返します。数字や記号が混在していても、英字がすべて大文字であれば True になります。 例 print(Hello world.isupper()) print(HELLO.isupper()) 出力 False True 最
-
Pythonで文字列が小文字のみで構成されているか判定する2つの方法
Pythonでは、文字列がすべて小文字で構成されているかどうかを簡単に判定できます。主な方法は2つあり、1つ目は文字列メソッドの islower() を使う方法、2つ目は正規表現を使う方法です。それぞれの特徴と違いを見ていきましょう。 方法1:islower() メソッドを使う islower() は、文字列内の英字がすべて小文字である場合に True を返します。数字やスペースなどの英字以外の文字は判定の対象外となる点に注意してください。 print(Hello world.islower()) print(hello world.islower()) 出力: False True