C++で二分木における最大部分木の合計を求める方法
この問題では、二分木(バイナリツリー)が与えられます。私たちのタスクは、木の中で最も大きな合計値を持つ部分木を見つけることです。
問題の概要
二分木には正の値と負の値が混在しています。その中から、ノードの合計が最大になる部分木を特定する必要があります。
例で問題を理解しよう

出力: 13
説明:
- 左部分木の合計:7
- 右部分木の合計:1
- 木全体の合計:13
このように、根を含む木全体の合計である「13」が最大の部分木の合計となります。
解法のアプローチ
この問題を解くためには、後順走査(ポストオーダー走査)を利用します。手順は以下の通りです。
- 左部分木と右部分木それぞれのノードの合計を再帰的に計算します。
- 現在のノードについて、「現在のノードを含む部分木の合計」が「左部分木または右部分木の合計」より大きいかどうかを確認します。
- 葉ノードから根ノードへと辿りながら、各段階での最大の合計を記録していきます。
後順走査を使うことで、子ノードの合計が確定した後に親ノードの合計を計算できるため、各ノードを一度だけ訪問する効率的な処理が可能になります。
ソリューションの実装プログラム
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は木の高さ)となります。
-
C++で二分木の各階層における最大値を見つける方法
二分木が与えられたとき、その木の各階層(レベル)ごとの最大値を求めることを考えます。例えば、次のような二分木があるとします。この場合、出力は [1, 3, 9] となります。ルート(最上位)の階層には「1」だけが存在するため、最大値は 1第1階層には「3」と「2」があり、最大値は 3第2階層には「5」「3」「9」があり、最大値は 9解決のためのアプローチこの問題は、再帰的な深さ優先探索(DFS) を使うことで簡潔に解くことができます。手順は以下の通りです。結果を格納するための配列 ans を定義します。再帰関数 solve() を定義します。この関数はツリーノードとレベル(初期値は 0)を引数
-
C++で二分木の最大垂直和を求める方法
はじめに二分木が与えられたとき、垂直順序走査における各垂直列のノード値の合計を計算し、その中から最大値を求めて出力するのが本記事の課題です。例として、以下のような二分木を考えてみましょう。この二分木を垂直順序走査すると、各列の合計は次のようになります。4 2 1 + 5 + 6 = 12 3 + 8 = 11 7 9各列の合計の中で最大となるのは 12 です。アルゴリズムの考え方アプローチはシンプルです。幅優先探索(BFS)を用いて垂直順序走査を行い、各ノードに水平距離を割り当てます。ルートの水平距離を 0 とし、左に移動するごとに -1、右に移動するごとに +1 とします。同じ水平距離を持つ