Pythonで配列をソートするために必要な最小スワップ回数を求めるプログラム
配列 nums が与えられたとき、その配列を昇順または降順のどちらかの順序でソートするために必要なスワップ(要素の交換)回数を求める問題を考えてみましょう。
例えば、入力が nums = [2, 5, 6, 3, 4] の場合、出力は 2 になります。最初、nums は [2, 5, 6, 3, 4] です。まず 6 と 4 を交換すると配列は [2, 5, 4, 3, 6] になり、続いて 5 と 3 を交換すると [2, 3, 4, 5, 6] となり昇順に整列します。つまり、この配列をソートするには 2 回のスワップが必要です。
解き方のアプローチ
この問題は、各要素が本来あるべき位置との対応関係を追跡し、循環(サイクル)を検出することで効率的に解けます。手順は以下の通りです。
- 関数
swap_count()を定義します。引数としてinput_arrを受け取ります。pos:=input_arrの各要素に対して (元の位置, 値) のタプルを格納した新しいリストを作成します。posを値に基づいてソートします。cnt:= 0 としてカウンタを初期化します。indexを 0 からinput_arrのサイズ未満まで繰り返します。- while True ループ内で次を判定します。
pos[index][0]がindexと一致していれば、正しい位置にあるのでループを抜けます。- そうでなければ、
cntを 1 増やし、swap_index:=pos[index][0]として、pos[index]とpos[swap_index]の内容を入れ替えます。
- while True ループ内で次を判定します。
cntを返します。
- メインとなる
solve()関数では、swap_count(input_arr)(昇順の場合)とswap_count(input_arr[::-1])(降順の場合)の小さい方を返します。これにより、「任意の順序でソートできる」という条件に対応できます。
実装例
理解を深めるために、実際のPythonコードを見てみましょう。
def swap_count(input_arr):
pos = sorted(list(enumerate(input_arr)), key=lambda x: x[1])
cnt = 0
for index in range(len(input_arr)):
while True:
if (pos[index][0] == index):
break
else:
cnt += 1
swap_index = pos[index][0]
pos[index], pos[swap_index] = pos[swap_index], pos[index]
return cnt
def solve(input_arr):
return min(swap_count(input_arr), swap_count(input_arr[::-1]))
nums = [2, 5, 6, 3, 4]
print(solve(nums))
入力
[2, 5, 6, 3, 4]
出力
2
ポイントまとめ
このアルゴリズムは、ソート後の正しい位置と現在の位置の対応関係をたどりながら、一連のサイクルごとに必要なスワップ回数を数えていく方法です。計算量はソート部分が O(n log n)、スワップの検出部分が O(n) となるため、全体として O(n log n) で動作し、大規模な配列でも効率的に処理できます。
-
Pythonで挿入ソート(Insertion Sort)を実装する方法:アルゴリズムとサンプルコードを徹底解説
この記事では、Python 3.x(およびそれ以前のバージョン)における挿入ソートの実装方法について詳しく解説します。挿入ソートは、トランプの手札を整理するイメージに近い、直感的で理解しやすいソートアルゴリズムです。挿入ソートのアルゴリズム挿入ソートは以下の手順で動作します。入力要素を順番に走査し、各反復ごとにソート済みの配列部分を少しずつ拡張していきます。現在注目している要素(キー)を、ソート済み部分の中で最も大きい値と比較します。キーがその値より大きければ、要素は元の位置のまま次の要素へ進みます。そうでなければ、ソート済み配列内の正しい位置を探し出し、そこへ移動させます。具体的には、ソート
-
Pythonで学ぶ挿入ソート(Insertion Sort)の仕組みと実装方法
この記事では、Python 3.xにおける挿入ソート(Insertion Sort)の基本的な考え方と、実際のコードによる実装方法をわかりやすく解説します。 挿入ソートのアルゴリズム 挿入ソートは、配列を「整列済みの部分」と「未整列の部分」に分け、未整列の要素を一つずつ取り出して、整列済み部分の正しい位置に挿入していくシンプルなソート手法です。処理の手順は以下の通りです。 1. 各反復ごとに整列済みの配列を少しずつ拡大しながら、入力要素を走査する。 2. 現在の要素(キー)を、整列済み配列内の最大値と比較する。 3. キーがその最大値より大きければ、要素はそのままの位置に置かれ、 次の要