Pythonで1回の文字スワップにより2つの文字列を等しくできるか判定するプログラム
同じ長さの2つの文字列 s と t があるとします。ここで考える操作とは、ある文字列の中から2つのインデックス(必ずしも異なる必要はありません)を選び、その位置の文字同士を入れ替えることです。本記事では、どちらか一方の文字列に対して最大1回のスワップを実行することで、2つの文字列を同じにできるかどうかを判定する方法を解説します。
たとえば、入力が s = "hello"、t = "hlelo" の場合、どちらか一方の文字列で e と l を入れ替えるだけで2つの文字列が一致するため、出力は True になります。
アルゴリズムの流れ
この問題は、以下の手順で解決できます。
- 許容される差の上限
max_diffsを 2 に設定します。 - 実際の差の個数
diffsを 0 で初期化します。 - s の文字を格納する集合
stと、t の文字を格納する集合st2を新しく作成します。 - i を 0 から s の長さまで順番に処理します。
s[i]とt[i]が異なる場合は、diffsを 1 増やします。s[i]がstに存在しなければ、stに追加します。t[i]がst2に存在しなければ、st2に追加します。diffsがmax_diffsを超えた場合は、即座にFalseを返します。
- 最終的に、「
diffsが 0 または 2」かつ「stとst2のサイズが等しい」かつ「stとst2の内容が一致する」場合にTrueを返し、それ以外はFalseを返します。
判定条件のポイント
最後の条件式が成り立つ理由は以下の通りです。
- diffs == 0 の場合: 2つの文字列は最初から一致しているため、スワップは一切不要です。
- diffs == 2 の場合: 異なる位置がちょうど2箇所あり、さらに両方の文字列に含まれる文字の種類が完全に一致していれば、1回のスワップで一致させることができます。
- その他の場合: 差が3箇所以上あると1回のスワップでは修正できません。また、差の位置があっても文字の構成(集合)が異なる場合、スワップによって一致させることは不可能です。
実装例
理解を深めるために、以下のPythonコードを見てみましょう。
def solve(s, t): max_diffs = 2 diffs = 0 st = set() st2 = set() for i in range(len(s)): if s[i] != t[i]: diffs += 1 if s[i] not in st: st.add(s[i]) if t[i] not in st2: st2.add(t[i]) if diffs > max_diffs: return False return (diffs == 0 or diffs == 2) and len(st) == len(st2) and st == st2 s = "hello" t = "hlelo" print(solve(s, t))
入力
"hello", "hlelo"
出力
True
-
Pythonで文字列が回文(パリンドローム)かどうかを判定する方法
文字列が与えられたとき、その文字列が回文(パリンドローム)であるかどうかを判定するのが、本記事の目的です。 回文とは、「madam」「level」「しんぶんし」のように、前から読んでも後ろから読んでも同じになる文字列のことを指します。Pythonでは、スライス記法を使うことで、わずか数行のコードでこの判定を実装できます。 アルゴリズム Step1: 文字列を入力として受け取る。 Step2: スライスを使って文字列を逆順にし、元の文字列と比較する。 Step3: 判定結果を表示する。 ポイント解説:スライスによる文字列の反転 このプログラムの核心は [::-1] というスライス記法です。こ
-
Pythonで文字列が回文かどうかを判定する方法
Pythonで回文判定を行う方法文字列が回文(前から読んでも後ろから読んでも同じになる文字列)であるかどうかを確認するには、Pythonの標準ライブラリに含まれる reversed() 関数を利用するのが便利です。この関数は逆順のイテレータオブジェクトを返し、それを list() でリストに変換することができます。手順1:reversed()で文字列を逆順にするまず、対象となる文字列を reversed() 関数に渡し、結果をリストとして取得します。>>> str1=malayalam >>> l1=list(reversed(str1)) >>