Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで解く「バディ文字列」問題:1回のスワップで2つの文字列を一致させられるか判定する

問題の概要

小文字だけで構成された2つの文字列 A と B が与えられたとします。このとき、A の中から2文字を選んで入れ替える(スワップする)操作をちょうど1回行うことで、A を B と一致させることができるかどうかを判定するのが「バディ文字列(Buddy Strings)」問題です。

例えば、入力が A = "ba"、B = "ab" の場合、先頭の2文字を入れ替えるだけで両者は一致するため、出力は True になります。

解法のアプローチ

この問題は、以下の手順に沿って判定することで効率的に解けます。

  • A と B の長さが異なる場合は False を返します。そもそも文字数が違えば、どんなスワップを行っても一致させることはできません。
  • A と B をそれぞれソートした結果が異なる場合(=使われている文字の種類や個数が一致しない場合)は False を返します。文字の構成が同じでなければ、順序の入れ替えだけでは一致しません。
  • A と B が完全に同一で、かつ A に含まれる文字がすべてユニーク(重複なし)である場合は False を返します。同一の文字列でも重複した文字が存在すれば、その2つを入れ替えても見た目は変わらないため True になり得ますが、すべてユニークな場合は必ずどこかが不一致になってしまいます。
  • 上記以外の場合は、各位置の文字を順番に比較して不一致の箇所をカウントします。カウントが3になった時点で False を返します(不一致箇所が2か所以内でなければ、1回のスワップでは一致させられないため)。ループが完了すれば True を返します。

なお、ソート済みの文字構成が一致しているという前提があるため、不一致箇所の数は必然的に偶数(0または2)になります。したがって「count == 3」のチェックで、3か所以上の不一致を確実に検出できます。

実装例

それでは、実際のコードを見て理解を深めましょう。

class Solution:
    def buddyStrings(self, A, B):
        if len(A) != len(B):
            return False
        elif sorted(A) != sorted(B):
            return False
        elif A == B and len(set(A)) == len(A):
            return False
        else:
            count = 0
            for i in range(len(A)):
                if A[i] != B[i]:
                    count += 1
                    if count == 3:
                        return False
        return True

ob = Solution()
print(ob.buddyStrings("ba", "ab"))

入力

"ba", "ab"

出力

True

計算量について

この解法の時間計算量は O(n log n)(ソート処理がボトルネック)、空間計算量は O(n) となります。n は文字列の長さです。ソートを使わずに文字の出現数をカウントする方式(Counterなど)を採用すれば、時間計算量を O(n) まで改善することも可能です。

  1. PythonのUnicode文字列とは?uプレフィックスの使い方をわかりやすく解説

    Pythonでは、通常の文字列は内部的に8ビットのASCIIとして保存されます。一方、Unicode文字列は16ビットのUnicodeとして保存され、世界中のほとんどの言語に含まれる特殊文字など、より多様な文字セットを扱うことができます。 ここでは、Unicode文字列の基本的な使い方について、以下のポイントに絞って解説します。 Unicode文字列の基本 PythonでUnicode文字列を定義するには、文字列の前に u プレフィックスを付けます。これは、raw文字列(エスケープシーケンスを無効化する文字列)に r プレフィックスを付けるのと同じ考え方です。 サンプルコード #!/usr/b

  2. Pythonの「%」演算子とは?文字列フォーマットの基本と使い方を解説

    Pythonの「%」演算子の役割 Pythonにおける「%(パーセント)」は、文字列フォーマット演算子(補間演算子)として機能します。「format % values」という形式で記述すると、フォーマット文字列内の変換指定子が、values側の要素によって置き換えられます。この仕組みは、C言語のsprintf()関数とよく似ています。 基本的な使い方:文字列の埋め込み 最もシンプルな例は、文字列の中に変数の値を埋め込むケースです。 >>> lang = Python >>> print %s is awesome! % lang Python is awe