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

Pythonで文字の削除・並べ替えにより生成できる最長回文を求めるアルゴリズム

問題の概要

ある文字列が与えられたとき、そこから文字を削除または並べ替え(シャッフル)することで作成できる最長の回文を見つけることを考えます。候補となる回文が複数存在する場合は、そのうちの1つを返せば十分です。

例えば、入力が pqqprrs の場合、出力は pqrsrqp になります。

解き方の考え方

回文とは、前から読んでも後ろから読んでも同じになる文字列のことです。回文を構成するには、各文字が中心を基準に左右対称にペアで配置されている必要があり、最大で1文字だけ中央に単独で置くことができます。

この性質を利用すると、以下の手順で最長回文を構築できます。

  1. サイズ256の配列 count を用意し、すべて0で初期化します。
  2. 文字列の先頭から末尾まで走査し、各文字のASCIIコードに対応する count の要素を1ずつ増やして、出現回数を記録します。
  3. 前半部分 begin、中央の文字 mid、後半部分 end の3つの空文字列を用意します。
  4. 変数 character を 'a' のASCIIコードで初期化し、'z' に達するまで以下を繰り返します。
    • count[character]奇数の場合:その文字を中央 mid として記録し、カウントを1減らしてから、同じ文字を偶数として再度処理できるようにポインタを1つ戻します。
    • count[character]偶数の場合:出現回数の半分の数だけ、その文字を begin に追加します。
  5. endbegin の逆順として設定します。
  6. begin + 中央の1文字 + end を連結した結果を返します。

実装例

理解を深めるために、以下のPythonによる実装を見てみましょう。

def get_palindrome(string):
    count = [0]*256
    for i in range(len(string)):
        count[ord(string[i])] += 1
    begin = ""
    mid = ""
    end = ""
    character = ord('a')
    while character <= ord('z'):
        if (count[character] & 1):
            mid = character
            count[character] -= 1
            character -= 1
        else:
            for i in range(count[character]//2):
                begin += chr(character)
        character += 1
    end = begin
    end = end[::-1]
    return begin + chr(mid) + end

string = "pqqprrs"
print(get_palindrome(string))

入力

"pqqprrs"

出力

pqrsrqp

計算量について

このアルゴリズムの時間計算量は O(n) です(n は文字列の長さ)。文字の出現回数を数えるのに O(n)、26種類の英小文字を走査して結果を構築するのにも合計で O(n) しかかかりません。空間計算量も O(n) であり、結果の文字列を格納するために必要となります。


  1. Pythonで文字列からn番目の文字を削除するプログラムの書き方

    はじめにこの記事では、以下の問題に対する解決方法を解説します。問題文 − 与えられた文字列から、指定したインデックス(i番目)の文字を削除し、その結果を表示します。Pythonの文字列では、インデックスは必ず0から始まるという点に注意してください。例えば、「Tutorialspoint」という文字列の場合、各文字のインデックスは以下のように対応しています。T u t o r i a l s p o i n t 0 1 2 3 4 5 6 7 8 9 10 11 12 13それでは、この問題を解決するためのPythonスクリプトを見ていきましょう。実装例def remove(string

  2. Pythonで文字列からn番目の文字を削除する方法【サンプルコード付き】

    Pythonにおいて、文字列は文字の配列として扱われます。そのため、先頭の文字のインデックスは「0」から始まり、各文字の位置(インデックス)を簡単に取得できます。この性質を利用すると、指定したn番目の文字だけを削除することが可能です。 基本的な考え方はシンプルです。削除したい文字のインデックス番号を受け取り、元の文字列を次の2つの部分文字列に分割します。 n番目のインデックスの文字より前の部分 n番目のインデックスの文字より後の部分 その後、この2つの部分文字列を連結すれば、n番目の文字が取り除かれた新しい文字列が完成します。 実行例 入力: python 削除するインデックス: 3 出