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

Pythonで二分木の最大平均サブツリーを求めるアルゴリズム

問題の概要

二分木のルートが与えられたとき、その木に含まれる任意の部分木の平均値の最大値を求めるのがこの問題の目的です。例として、次のような二分木を考えてみましょう。

Pythonで二分木の最大平均サブツリーを求めるアルゴリズム

この場合の出力は 6 になります。理由は以下の通りです。

  • ノード5を根とする部分木:(5 + 6 + 1) / 3 = 4
  • ノード6を根とする部分木:6 / 1 = 6
  • ノード1を根とする部分木:1 / 1 = 1

これらの中で最も大きいのは6なので、答えは6となります。

解法のアプローチ

この問題は後順走査(post-order traversal)による再帰を使うことで効率的に解けます。各ノードについて「その部分木のノード数」と「その部分木の合計値」をペアで返しながら、途中経過で平均値を更新していくのがポイントです。

具体的には、以下の手順で処理を進めます。

  1. 結果を格納する変数 res を0で初期化します。
  2. solve() というメソッドを定義し、ノードを引数として受け取ります。
  3. ノードが存在しない場合は、ペア [0, 0](ノード数0、合計値0)を返します。
  4. 左右の子ノードに対して solve() を再帰的に呼び出します。
  5. 現在の部分木のノード数 c を「左のノード数 + 右のノード数 + 1」として計算します。
  6. 現在の部分木の合計値 s を「左の合計値 + 右の合計値 + 現在のノードの値」として計算します。
  7. ans を「anss / c のうち大きい方」で更新します。
  8. ペア [c, s] を呼び出し元に返します。
  9. メインのメソッドでは ans を0に初期化し、solve(root) を呼び出した後に ans を返します。

実装例(Python)

理解を深めるために、以下のPythonコードを見てみましょう。

class TreeNode:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

def insert(temp, data):
    que = []
    que.append(temp)
    while len(que):
        temp = que[0]
        que.pop(0)
        if not temp.left:
            if data is not None:
                temp.left = TreeNode(data)
            else:
                temp.left = TreeNode(0)
            break
        else:
            que.append(temp.left)
        if not temp.right:
            if data is not None:
                temp.right = TreeNode(data)
            else:
                temp.right = TreeNode(0)
            break
        else:
            que.append(temp.right)

def make_tree(elements):
    Tree = TreeNode(elements[0])
    for element in elements[1:]:
        insert(Tree, element)
    return Tree

class Solution(object):
    def helper(self, node):
        if not node:
            return 0, 0
        left_sum, left_count = self.helper(node.left)
        right_sum, right_count = self.helper(node.right)
        self.ans = max(self.ans, (left_sum + right_sum + node.data) / (left_count + right_count + 1))
        return left_sum + right_sum + node.data, left_count + right_count + 1

    def maximumAverageSubtree(self, root):
        self.ans = 0
        self.helper(root)
        return self.ans

ob = Solution()
root = make_tree([5, 6, 1])
print(ob.maximumAverageSubtree(root))

入力

[5,6,1]

出力

6.0

計算量の評価

このアルゴリズムは各ノードを一度だけ訪問するため、時間計算量はO(n)(nはノード数)です。また、再帰の深さは木の高さに依存するため、バランスの取れた木では空間計算量はO(log n)、最悪ケース(線形リスト状に偏った木)ではO(n)となります。

なお、ノードの値に負の数が含まれる可能性がある場合は、ans の初期値を0ではなく float('-inf')(負の無限大)にしておくと、より安全に動作します。

  1. 【Python入門】3つの数値から最大値を求める方法

    3つの数値 a、b、c が与えられたとき、その中で最も大きい要素(最大値)を見つけるのが今回の課題です。ここでは、Pythonのリストと組み込み関数 max() を使ったシンプルな方法を、初心者向けにわかりやすく解説します。 実行例 入力:a = 2, b = 4, c = 3 出力:4 アルゴリズム ステップ1:ユーザーから3つの数値を入力として受け取る。 ステップ2:3つの数値をリストに格納する。 ステップ3:max() 関数を使ってリスト内の最大値 max(lst) を求める。 ステップ4:最後に最大値を出力する。 サンプルコード def maximum(a, b, c):

  2. Pythonでリストの平均値を求める方法

    Pythonには、複数の要素の合計を簡単に計算できる組み込み関数 sum() が用意されています。ここでは、この関数を使ってリスト内のすべての数値の合計を求め、その後、合計を要素数で割ることで平均値を計算します。 アルゴリズム ステップ1:「リストのサイズ」を入力する ステップ2:「要素」を入力する ステップ3:sum関数を使用して、すべての数値の合計を計算する ステップ4:平均値を計算する サンプルコード # リストの平均値を求める A=list() n=int(input(Enter the size of the List ::)) print(Enter the number :