再帰で 二分木の 道の 値の 合計が いちばん 大きくなる所を探す
二分木の
海外で定番の問題リスト 4 本には入っていません
問題
二分木のroot を
- 道は、
親と 子を 結ぶ 辺を たどって、 同じ節を 2 回通らずに つないだ節の 列です。 節が 1 つだけでも道です - 道は
根を 通らなくてもかまいません。 ある 節で 左の 枝から 上がってきて右の 枝へ 降りる、という 曲がり方は 1 回だけできます - 値には
負の 数も あります。 全部が 負なら、 答えは いちばん 大きい 1 つの 節の値です - 各節は
val(値)、left(左の子)、 right(右の子) を 持ちます。 子が 無い ところは、 Python では None、JavaScript では null、Go では nilです。Go の 節は TreeNodeで、Val、Left、Rightと大文字で 始まります - 節の
数は 1 以上 500 以下、 値は どれも -1000 以上 1000 以下です
例では、null です。
入力と出力の例
例 1
根が 2、
例 2
根の -6 を
例 3
全部の
面接での聞かれ方
木の
- 「二分木の
道の 合計の 最大を 求めてください。 道は 根を 通らなくても よく、 値には 負の 数も あります」 - 二分木の
直径を 求める 問題 (この 一覧の tree-diameter) と 同じ形で、 辺の 数の 代わりに 値を 足し、 負の 値を 捨てる 判断が 加わった物です - 「どの
道が 最大か、 道その ものも 返せますか?」と 続けて 聞かれる ことがあります
シニアの
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「再帰と木」に、
関わる学び
再帰は、
まず 考える手順
段 1
まずは
段 2
どの
段 3
「子から
段 4
片道の
解答
Python
Python
def max_path_sum(root):
best = root.val
def down(n):
nonlocal best
if n is None:
return 0
l = down(n.left)
r = down(n.right)
l = max(l, 0)
r = max(r, 0)
here = n.val + l + r
best = max(best, here)
return n.val + max(l, r)
down(root)
return bestJavaScript
JavaScript
function maxPathSum(root) {
let best = root.val;
const down = (n) => {
if (n === null) {
return 0;
}
const l = Math.max(
down(n.left), 0);
const r = Math.max(
down(n.right), 0);
best = Math.max(
best, n.val + l + r);
return n.val
+ Math.max(l, r);
};
down(root);
return best;
}Go
Go
func maxPathSum(
root *TreeNode,
) int {
best := root.Val
var down func(*TreeNode) int
down = func(n *TreeNode) int {
if n == nil {
return 0
}
l := max(down(n.Left), 0)
r := max(down(n.Right), 0)
best = max(best, n.Val+l+r)
return n.Val + max(l, r)
}
down(root)
return best
}down がbest を
計算量
- 時間は O(n) です。
どの 節にも 1 回ずつ 行き、 子から 返った 値を 比べるだけです - 使う
記憶は O(h) です。 h は 木の 高さで、 再帰の 呼び出しが 深さの 分だけ積まれます。 1 本道の 木では O(n) に なります。 節が 500 以下なので、 Python の 再帰の 上限 (1000 段) には 届きません
よく ある間違い
- 親へ
左右の 両方を 足した 値を返す。 両方を 足した 道は、 その節で 曲がっています。 親へつなぐと 2 回曲がる 形に なり、 道ではなくなります。 親へ返すのは 片方だけです - 負の
枝を 捨てない。 子からの 片道が 負の ときに 足すと、 その 分だけ合計が 下がります。 例 3 で、 根の -3 から 見て 左の -2 を 足すと -5 に なり、 正しくは 足さずに 比べます。 0 と 比べて 大きい方を使います bestを 0 から始める。 全部が負の 木では 答えが 負なので、 例 3 で 0 を 返してしまいます。 根の 値か、 いちばん 小さい 数から始めます - 根を
通る 道だけを見る。 例 2 のように、 根を 通らない 道が 最大の ことがあります。 すべての 節で、 その節で 曲がる 道を比べます
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「どの
道にも いちばん上の 節が 1 つ あるので、 節ごとに そこで 曲がる 道の 最大を 比べます。 再帰では、 子から 下へ 伸びる 片道の 最大を 返して もらい、 負なら 0 に して 捨てます。 その節で 曲がる 道は 自分と 左右の 片道の 和で、 これを 最大と 比べ、 親へは 自分と 大きい片方だけの 和を 返します。 時間は O(n) です。」
書き終えたら、
「例 1 では、
5 と 1 と 9 は 葉なので、 片道は それぞれ 5、 1、 9 です。 6 では 左右が 5 と 1 で、 曲がる 道は 12、 親へは 11 を 返します。 -4 では 右が 9 で、 曲がる 道は 5、 親へは 5 を 返します。 根の 2 では 左が 11、 右が 5 で、 曲がる 道は 18 で、 これが 最大です。」