深さ優先探索で 根からの 道で いちばん 大きい値を 持ち回り、 二分木の よい 節を数える
根から
海外で定番の問題リスト 4 本には入っていません
問題
二分木のroot を
- 道の
途中に、 その節と 同じ値が あってもかまいません。 大きい値が 無ければ よい節です - 根は、
道に 自分しかいないので、 いつも よい節です - 各節は
val(値)、left(左の子)、 right(右の子) を 持ちます。 子が 無い ところは、 Python では None、JavaScript では null、Go では nilです。Go の 節は TreeNodeで、Val、Left、Rightと大文字で 始まります - 節の
数は 1 以上 500 以下、 値は どれも -10000 以上 10000 以下です
例では、null です。
入力と出力の例
例 1
山道の
例 2
根の 4 の
例 3
節が 1 つだけの
面接での聞かれ方
木の
- 「根からの
道に 自分より 大きい値が 無い節を 数えてください」 - 木の
深さを 求める 問題の ように 「下から上へ値を返す」 再帰と 比べて、 「上から下へ引数で渡す」 再帰の 書き方を 見る ために 出されます - 「再帰を
使わずに 書けますか?」と 聞かれる ことがあります。 節と、 そこまでの 最大値の 組を スタックに 積めば 同じことができます
ミドルの
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「再帰と木」に、
関わる学び
再帰は、
まず 考える手順
段 1
まずは
段 2
ある
段 3
そこで、
段 4
根は、
解答
Python
Python
def good_nodes(root):
def walk(n, best):
if n is None:
return 0
ok = int(n.val >= best)
top = max(best, n.val)
a = walk(n.left, top)
b = walk(n.right, top)
return ok + a + b
return walk(root, root.val)JavaScript
JavaScript
function goodNodes(root) {
const walk = (node, best) => {
if (node === null) {
return 0;
}
const good =
node.val >= best ? 1 : 0;
const top =
Math.max(best, node.val);
return good
+ walk(node.left, top)
+ walk(node.right, top);
};
return walk(root, root.val);
}Go
Go
func goodNodes(
root *TreeNode,
) int {
return walkGood(
root, root.Val)
}
func walkGood(
n *TreeNode, best int,
) int {
if n == nil {
return 0
}
good := 0
if n.Val >= best {
good = 1
}
best = max(best, n.Val)
return good +
walkGood(n.Left, best) +
walkGood(n.Right, best)
}best は、
計算量
- 時間は O(n) です。
どの 節にも 1 回ずつ 行き、 比べるのは 1 回だけです - 使う
記憶は O(h) です。 h は 木の 高さで、 再帰の 呼び出しが 深さの 分だけ積まれます。 1 本道の 木では O(n) に なります。 節が 500 以下なので、 Python の 再帰の 上限 (1000 段) には 届きません
よく ある間違い
>で比べる。 道に同じ値が あっても よい節です。 例 2 の 左の 4 は、 道の 根も 4 ですが、 よい節です。 >=で比べます- 親の
値とだけ比べる。 親より 大きくても、 もっと 上に より 大きい値が あれば よい 節では ありません。 渡すのは、 道全体の 最大値です - 最大値を
外の 変数に 持ち、 戻る ときに 戻し忘れる。 左の 枝で 上げた 最大値が、 右の 枝にまで 残ります。 引数で 渡せば、 枝ごとに 別の 値になります - 最初の
最大値を 0 にする。 値は 負の 数も あるので、 例 3 の -5 が 0 より 小さく、 よい 節と 数えられません。 根の 値か、 いちばん 小さい 数から始めます
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「よい
節か どうかに 要るのは、 根からの 道で いちばん 大きい値だけです。 深さ優先探索で、 ここまでの 最大値を 引数として 子へ 渡し、 自分の 値が それ以上 なら 1 と 数えます。 子へは 自分の 値も 含めた 最大値を 渡します。 時間は O(n)、 記憶は 木の 高さの 分です。」
書き終えたら、
「例 1 では、
根の 5 は 最大値 5 以上 なので 数え、 左の 3 は 5 より 小さいので 数えません。 その下の 6 は、 最大値 5 以上 なので 数えます。 右の 8 は 数えて 最大値を 8 にし、 下の 2 は 数えず、 9 は 数えます。 合わせて 4 つです。」