【Python】1回のスワップで作れる辞書式順序で最小の文字列を求める方法
問題の概要
文字列 s が与えられたとき、文字列内の2つの文字を最大1回だけ入れ替える(スワップする)ことで得られる、辞書式順序で最も小さい文字列を求めます。
例えば、入力が "zyzx" の場合、出力は "xyzz" となります。最初の文字 z を x と入れ替えることで、辞書式順序で最小の文字列が得られます。
解法のアプローチ
この問題を解くために、以下の手順に従います。
temp:文字列sと同じサイズの配列を作成し、0で初期化します。m:文字列の長さから1を引いた値(末尾のインデックス)で初期化します。iを文字列の末尾から先頭へ向かってループさせます。s[i] < s[m]の場合、m = iと更新します。temp[i] = mを記録します。これにより、「位置i以降で最も小さい文字のインデックス」が各位置ごとに保存されます。
- 次に、
iを先頭から末尾までループさせます。a = temp[i]とします。s[a]がs[i]と異なる場合、i番目とa番目の文字を入れ替えた結果の文字列を返します。
- どの入れ替えでも文字列が改善されない場合は、元の文字列
sをそのまま返します。
実装例
class Solution:
def solve(self, s):
temp = [0]*len(s)
m = len(s)-1
for i in range(len(s)-1, -1, -1):
if s[i]<s[m]: m=i
temp[i] = m
for i in range(len(s)):
a = temp[i]
if s[a] != s[i]:
return s[:i]+s[a]+s[i+1:a]+s[i]+s[a+1:]
return s
ob = Solution()
print(ob.solve("zyzx"))
入力
zyzx
出力
xyzz
アルゴリズムのポイント
このアルゴリズムの鍵は、右側から事前走査を行う点にあります。末尾から順に処理することで、「各位置より後ろにある最小の文字」のインデックスを temp 配列に効率的に記録できます。
その後、先頭から走査し、現在の文字よりも小さい文字が後方に存在する最初の位置を見つけたら、そこを入れ替えます。これにより、できるだけ前方の文字を小さくすることができ、結果として辞書式順序で最小の文字列が得られます。
計算量は前走査・後走査ともに線形時間であるため、全体の時間計算量は O(n)、空間計算量も補助配列分の O(n) となり、非常に効率的な解法です。
-
Pythonで指定されたインデックスに基づいて文字列をシャッフルする方法
文字列 s とインデックスのリスト ind が与えられ、両者は同じ長さであるとします。文字列 s は、位置 i にある文字が最終的な文字列内の ind[i] の位置へ移動するようにシャッフルされます。このとき、シャッフル後の最終的な文字列を求める必要があります。例えば、入力が s = ktoalak、ind = [0,5,1,6,2,4,3] の場合、出力は kolkata となります。解決手順この問題を解くには、以下の手順に従います。fin_str を s と同じサイズのリストとして作成し、0で初期化するs 内の各インデックス i と各文字 v に対して、次の操作を行うfin_str[ind
-
Pythonでリスト内の最小値を見つける方法を解説
この記事では、リストの中から最小の数値を見つける方法について、具体的なサンプルコードとともに詳しく解説します。問題の概要問題: 数値のリストが与えられたとき、その中に含まれる最も小さい数値を画面に表示すること。この問題を解くアプローチは主に2つあります。ひとつは sort() メソッドを使ってリストを昇順に並べ替え、先頭の要素(インデックス0)を取得する方法。もうひとつは、Pythonに標準で用意されている組み込み関数 min() を使う方法です。それぞれ順番に見ていきましょう。方法1:sort()メソッドで並べ替えて最小値を取得するまずはリストを昇順にソートし、先頭の要素を取り出す方法です。