リリース・改善中
Algorithm
分割統治法は、問題を小さな部分問題に分けて再帰的に解き、その結果を組み合わせる設計手法で、マージソートや高速べき乗の土台です。
分割統治法(divide and conquer)は、問題を同じ形のより小さな部分問題に分け(分割)、それぞれを再帰的に解き(統治)、その答えを組み合わせて元の問題の答えを作る(統合)アルゴリズム設計手法です。マージソート、二分探索、高速べき乗(繰り返し二乗法)、クイックセレクト、カラツバ法、最近点対問題のアルゴリズムがこの形に従います。
重要なのは、全通りを調べる O(n^2) の解法を O(n log n) や O(log n) に縮められる場面が多いからです。転倒数の計算のように、分割の境界をまたぐ情報を統合の段階で効率よく求める発想はコーディング面接や競技プログラミングで頻出で、ソートライブラリ、多倍長整数の乗算、FFT、暗号のべき乗剰余など実際のシステムでも使われています。
まずマージソートを手でトレースして分割・統治・統合の流れをつかみ、T(n) = aT(n/b) + f(n) のような漸化式を立ててマスター定理で計算量を求める練習をします。続いて転倒数、高速べき乗、クイックセレクトを自分で実装し、部分問題が重なる場合は動的計画法が必要になるという違いを見分けられるようにしましょう。
入力を分割し、部分を再帰的に解き、答えを統合します。基底ケースが再帰を止め、たいていは統合のコストが全体の計算量を決めます。
実行時間を T(n) = aT(n/b) + f(n) と書き、f(n) を n^(log_b a) と比べることで、マージソートの O(n log n) のような結果をすぐに得られます。
転倒数や最大部分配列和のように、両方の半分にまたがるケースを統合段階で線形時間に処理することが中心的な発想です。
二分探索、高速べき乗、クイックセレクトのように部分問題を1つだけ残すと、O(log n) や期待値 O(n) のアルゴリズムになります。
sort_count はマージソートでリストを並べ替えながら、右半分の要素が先に取り出されるたびに左側に残っている要素数を足し、転倒数を O(n log n) で数えます。power は指数を半分にしながら二乗する高速べき乗で、乗算は O(log e) 回で済みます。python divide_and_conquer.py を実行すると、ソート結果と転倒数 14、3^200 を 1,000,000,007 で割った余りが表示されます。
divide_and_conquer.py
def sort_count(a):
"""Return (sorted list, number of inversions) using merge sort."""
if len(a) <= 1:
return list(a), 0
mid = len(a) // 2
left, x = sort_count(a[:mid])
right, y = sort_count(a[mid:])
merged, i, j, cross = [], 0, 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
merged.append(left[i])
i += 1
else:
merged.append(right[j])
j += 1
cross += len(left) - i # right[j] is smaller than every left[i:]
merged += left[i:] + right[j:]
return merged, x + y + cross
def power(base, exp, mod):
"""base ** exp % mod with O(log exp) multiplications."""
if exp == 0:
return 1 % mod
half = power(base, exp // 2, mod)
result = half * half % mod
return result * base % mod if exp % 2 else result
if __name__ == "__main__":
print(sort_count([5, 2, 4, 7, 1, 3, 2, 6])) # ([1, 2, 2, 3, 4, 5, 6, 7], 14)
print(power(3, 200, 1_000_000_007)) # 136318165
python divide_and_conquer.pyインストールから 分割統治法 の中心となる考え方まで、6 章で順を追って学びます。
分割統治法 について質問し、経験を共有し、意見を交わす場所です。
まだディスカッションはありません。最初の話題を始めましょう。
コメント 0件
ログイン · ログインするとコメントできます。
最初のコメントを書いてみましょう。