Pythonでリストが最大ヒープ(Max Heap)かどうかを判定する方法
数値のリスト nums が与えられたとき、そのリストが最大ヒープ(Max Heap)として成立しているかどうかを判定する問題について解説します。
最大ヒープの条件
リストが最大ヒープであるためには、以下のルールをすべて満たす必要があります。
- インデックス
2*i + 1が範囲内に存在する場合、nums[i] >= nums[2*i + 1]が成り立つこと - インデックス
2*i + 2が範囲内に存在する場合、nums[i] >= nums[2*i + 2]が成り立つこと
つまり、各親ノードの値が、その子ノードの値以上でなければなりません。これはヒープ構造の基本的な性質です。
入力例と出力
たとえば、入力が [5, 3, 4, 1, 2] の場合、出力は True になります。このリストでは、親ノードが常に子ノード以上の値を持っているためです。
解法のアプローチ
この問題を解くためには、以下の手順に従います。
iを 0 から(numsのサイズ) // 2 - 1まで繰り返しますnums[i] >= nums[2*i+1]が成り立たない場合はFalseを返しますi*2+2 <= len(nums)-1の場合(右の子が存在する場合)、nums[i] >= nums[2*i+2]が成り立たなければFalseを返します
- すべてのチェックを通過したら
Trueを返します
ポイントは、葉ノード(子を持たないノード)はチェックする必要がないため、ループ範囲をリストの前半分だけに限定できることです。これにより計算量を抑えられます。
Pythonでの実装例
以下のコードで実際の実装を確認してみましょう。
class Solution: def solve(self, nums): for i in range(len(nums)//2): if not nums[i] >= nums[2*i+1]: return False if i*2+2 <= len(nums)-1: if not nums[i] >= nums[2*i+2]: return False return True ob = Solution() nums = [5, 3, 4, 1, 2] print(ob.solve(nums))
入力
[5, 3, 4, 1, 2]
出力
True
まとめ
このアルゴリズムの計算量は O(n/2)、つまり O(n) であり、リストの要素数に対して線形時間でヒープ性を検証できます。空のリストや要素が1つのリストの場合も、ループが実行されずに True が返されるため、正しく動作します。ヒープソートや優先度付きキューの実装を理解するうえで、この判定ロジックは非常に有用な基礎知識となります。
-
【Python】リストが最大ヒープを形成しているかどうかを判定する方法
リストがヒープツリー(完全二分木)を表していると仮定します。このとき、その要素が最大ヒープ(max heap)を形成しているかどうかを判定する必要があります。 最大ヒープとは、すべての親ノードがその左右の子ノードのどちらよりも大きい(または等しい)という性質を持つヒープのことです。 たとえば、入力が nums = [8, 6, 4, 2, 0, 3] の場合、出力は True になります。これは、すべての親要素がそれぞれの子要素より大きいためです。 解決手順 この問題は、次の手順で解決できます。 n := nums のサイズとする i を 0 から n - 1 までループする m :=
-
Pythonでヒープソートを実装する方法をわかりやすく解説
この記事では、配列をヒープソート(Heap Sort)のアルゴリズムを使って並べ替えるPythonプログラムについて解説します。 問題の概要 問題文: 与えられた配列を、ヒープソートの考え方を用いて昇順にソートします。 ヒープソートでは、まず配列を最大ヒープ(親ノードが常に子ノード以上の値を持つ二分木構造)に構築します。その後、最大値であるルート要素を配列の末尾と交換し、残りの部分に対して再度ヒープ化を行うという操作を繰り返します。これにより、大きな値から順に後ろへ確定していき、最終的に配列全体がソートされます。 それでは、実際の実装例を見ていきましょう。 実装例 # ヒープ化処理 def h