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

Pythonでマージソートの再帰呼び出しがちょうどk回になる配列を見つける方法

問題の概要

2つの整数 a と b が与えられたとき、[1, a] の範囲の値をすべて含み、再帰的なマージソート関数がちょうど b 回呼び出されるような配列を見つけることを考えます。

例えば、入力が a = 10、b = 15 の場合、出力は次のようになります。

[3, 1, 4, 6, 2, 8, 5, 9, 10, 7]

解法のアプローチ

この問題は、再帰関数を使って配列を構築しながら、要素の入れ替えによってマージソートの呼び出し回数を調整することで解けます。手順は以下の通りです。

  • 再帰関数 solve(left, right, array, b) を定義します。
  • b < 1 または区間の幅が1(left + 1 == right)の場合は、それ以上処理せずに return します。
  • b を 2 減らします(b := b − 2)。
  • 中央位置 mid := (left + right) // 2 を求めます。
  • array[mid − 1] と array[mid] の値を入れ替えます。
  • solve(left, mid, array, b) と solve(mid, right, array, b) を再帰的に呼び出します。

メインの関数では次のように処理します。

  • b が偶数の場合は「None」を表示して終了します(後述の理由により、解は必ず奇数回になります)。
  • サイズ a + 2 の配列を 0 で初期化し、array[0] = 1、array[i] = i + 1(i = 1 ~ a − 1)として [1, a] の値を設定します。
  • b を 1 減らしてから solve(0, a, array, b) を呼び出します。
  • 最後に配列とサイズ a を返します。

実装例

以下にPythonでの実装例を示します。

def solve(left, right, array, b):
    if (b < 1 or left + 1 == right):
        return
    b -= 2
    mid = (left + right) // 2
    temp = array[mid - 1]
    array[mid - 1] = array[mid]
    array[mid] = temp
    solve(left, mid, array, b)
    solve(mid, right, array, b)

def find_arr(a, b):
    if (b % 2 == 0):
        print("None")
        return
    array = [0 for i in range(a + 2)]
    array[0] = 1
    for i in range(1, a):
        array[i] = i + 1
    b -= 1
    solve(0, a, array, b)
    return array, a

a = 10
b = 15
array, size = find_arr(a, b)
print(array[:size])

入力と出力

入力:

10, 15

出力:

[3, 1, 4, 6, 2, 8, 5, 9, 10, 7]

仕組みの解説

長さ n の配列に対してマージソートを完全に実行すると、再帰呼び出しは合計 2n − 1 回発生します。n = 10 の場合は 19 回です。

このアルゴリズムでは、再帰の各段階で中央付近の隣接要素を入れ替えることで、一部の区間が早い段階で整列済みの状態になります。その結果、それ以上の分割・再帰が不要となり、1回の入れ替えにつき呼び出し回数を2回ずつ減らすことができます。

したがって、実現可能な呼び出し回数は常に奇数となります。これが、b が偶数の場合に「None」を返す理由です。a = 10、b = 15 の例では、19 回から 4 回(=入れ替え2回分)減らしてちょうど 15 回の呼び出しを実現しています。

  1. Pythonでマージソートを実装する方法をわかりやすく解説

    マージソート(Merge Sort)は、代表的なソートアルゴリズムのひとつです。ソート対象の配列の長さを n とすると、計算量は O(n log n) となり、非常に効率的な並べ替え手法として知られています。 マージソートは「分割統治法(Divide and Conquer)」という考え方に基づいたアルゴリズムです。まず、配列を半分ずつに再帰的に分割していき、要素が1つになるまで分割を続けます。その後、要素が1つだけのリスト同士を順にマージ(併合)しながら整列させていき、最終的に完全にソートされたリストを作り上げます。 この一連の処理によって、整列済みの配列を得ることができます。 マージソー

  2. Pythonでマージソートを実装する方法を徹底解説!サンプルコード付き

    この記事では、マージソート(Merge Sort)のアルゴリズムを使って配列を並べ替えるPythonプログラムについて、実際のコード例を交えながら詳しく解説します。 問題設定 課題 − 与えられた配列を、マージソートの考え方を用いて昇順に並べ替えます。 マージソートは分割統治法に基づく整列アルゴリズムです。まず配列を半分ずつ再帰的に分割し、要素が1つになった時点でそれを「ソート済み」とみなします。その後、隣り合う部分配列同士を先頭から比較しながら統合(マージ)していくことで、最終的に配列全体が整列されます。 Pythonでの実装例 # マージ関数 def merge(arr, l, m,