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

C++で二分木における最大部分木の合計を求める方法

この問題では、二分木(バイナリツリー)が与えられます。私たちのタスクは、木の中で最も大きな合計値を持つ部分木を見つけることです。

問題の概要

二分木には正の値と負の値が混在しています。その中から、ノードの合計が最大になる部分木を特定する必要があります。

例で問題を理解しよう

C++で二分木における最大部分木の合計を求める方法

出力: 13

説明:

  • 左部分木の合計:7
  • 右部分木の合計:1
  • 木全体の合計:13

このように、根を含む木全体の合計である「13」が最大の部分木の合計となります。

解法のアプローチ

この問題を解くためには、後順走査(ポストオーダー走査)を利用します。手順は以下の通りです。

  1. 左部分木と右部分木それぞれのノードの合計を再帰的に計算します。
  2. 現在のノードについて、「現在のノードを含む部分木の合計」が「左部分木または右部分木の合計」より大きいかどうかを確認します。
  3. 葉ノードから根ノードへと辿りながら、各段階での最大の合計を記録していきます。

後順走査を使うことで、子ノードの合計が確定した後に親ノードの合計を計算できるため、各ノードを一度だけ訪問する効率的な処理が可能になります。

ソリューションの実装プログラム

C++コード例

#include <iostream>
using namespace std;

struct Node {
    int key;
    Node *left, *right;
};

Node* newNode(int key) {
    Node* temp = new Node;
    temp->key = key;
    temp->left = temp->right = NULL;
    return temp;
}

int calcSumTreeSumRec(Node* root, int& ans) {
    if (root == NULL)
        return 0;
    int currSum = root->key + calcSumTreeSumRec(root->left, ans) + calcSumTreeSumRec(root->right, ans);
    ans = max(ans, currSum);
    return currSum;
}

int calcMaxSubTreeSum(Node* root)
{
    if (root == NULL)
        return 0;
    int ans = -100;
    calcSumTreeSumRec(root, ans);
    return ans;
}

int main() {

    Node* root = newNode(5);
    root->left = newNode(-4);
    root->right = newNode(4);
    root->left->left = newNode(3);
    root->left->right = newNode(8);
    root->right->left = newNode(-5);
    root->right->right = newNode(2);

    cout<<"The largest subtree sum is "<<calcMaxSubTreeSum(root);
    return 0;
}

出力結果

The largest subtree sum is 13

コードのポイント

  • calcSumTreeSumRec 関数は再帰的に各ノードの部分木の合計を計算し、その都度これまでの最大値 ans を更新します。
  • 初期値を負の数に設定することで、すべてのノードが負の値の場合にも正しく動作します。
  • 計算量は各ノードを一度だけ訪問するため O(N)、空間計算量は再帰の深さ分の O(H)(Hは木の高さ)となります。
  1. C++で二分木の各階層における最大値を見つける方法

    二分木が与えられたとき、その木の各階層(レベル)ごとの最大値を求めることを考えます。例えば、次のような二分木があるとします。この場合、出力は [1, 3, 9] となります。ルート(最上位)の階層には「1」だけが存在するため、最大値は 1第1階層には「3」と「2」があり、最大値は 3第2階層には「5」「3」「9」があり、最大値は 9解決のためのアプローチこの問題は、再帰的な深さ優先探索(DFS) を使うことで簡潔に解くことができます。手順は以下の通りです。結果を格納するための配列 ans を定義します。再帰関数 solve() を定義します。この関数はツリーノードとレベル(初期値は 0)を引数

  2. C++で二分木の最大垂直和を求める方法

    はじめに二分木が与えられたとき、垂直順序走査における各垂直列のノード値の合計を計算し、その中から最大値を求めて出力するのが本記事の課題です。例として、以下のような二分木を考えてみましょう。この二分木を垂直順序走査すると、各列の合計は次のようになります。4 2 1 + 5 + 6 = 12 3 + 8 = 11 7 9各列の合計の中で最大となるのは 12 です。アルゴリズムの考え方アプローチはシンプルです。幅優先探索(BFS)を用いて垂直順序走査を行い、各ノードに水平距離を割り当てます。ルートの水平距離を 0 とし、左に移動するごとに -1、右に移動するごとに +1 とします。同じ水平距離を持つ