ゆめさくエンジニア研究所
木の走査問題 17

根から​葉までの​合計が​目標に​なる​道があるか

二分木の​根から​葉までの​道で、​値の​合計が​目標の​数に​なる物が​あるかを​調べる。​残りの​数を​子へ​渡しながら​潜る、​深さ優先の​再帰の​練習です。

問題

二分木の根 root と、整数 target を受け取ります。根から葉までの道のうち、通った節の値の合計が target になる物が 1 本でもあれば true、無ければ false を返す関数を書いてください。

  • 葉とは、左の子も右の子も無い節のことです。道は必ず根から始まり、葉で終わります
  • 各節は val (値)、left (左の子)、right (右の子) を持ちます。子が無いところは、Python では None、JavaScript では null です
  • 木が空のときは、道が 1 本も無いので false を返します
  • 節の数は 0 以上 500 以下、値は -1000 以上 1000 以下で、負の数もあります。target は -100000 以上 100000 以下です

例では、木を上の段から左の順に読んだ値の並びで書きます。子が無いところは null です。

入力と出力の例

例 1

根 6 から 3、-2 と下りる道の合計が 7 になります。

入力

root = [6, 3, 9, -2, 4, null, 1]
target = 7

出力

true

例 2

途中の 4 と 3 で合計が 7 になり、目標の 5 を超えます。それでも、次の -2 で 5 に戻ります。

入力

root = [4, 3, null, -2]
target = 5

出力

true

例 3

根の 1 だけで合計は 1 ですが、根には子の 2 があるので葉ではありません。根から葉までの道は 1 と 2 の 1 本だけで、合計は 3 です。

入力

root = [1, 2]
target = 1

出力

false

面接での聞かれ方

面接では、次のように短く渡されることが多いです。

  • 「二分木と数が渡されます。根から葉まで足して、その数になる道はありますか」
  • 書き終えたあとに「その道そのものを返せますか?」「当てはまる道を全部返せますか?」と広げて聞かれます
  • 「再帰を使わずに書けますか?」と聞かれることもあります

書き始める前に、葉の意味 (子が 1 つも無い節) と、値に負の数があるかを確かめておくと、あとの間違いを防げます。

まず考える手順

段 1

まずは素直に、根から葉までの道を全部書き出す方法を考えます。道ごとに値を並べて足し、target と比べます。正しく動きますが、道を並びとして持ち歩くので、手間も記憶も余計にかかります。

段 2

道を全部持たなくても、合計だけ分かれば足ります。そこで、子へ下りるときに「あといくつ足せば目標になるか」という残りの数を渡します。残りは、いまの節の値を target から引いた数です。

段 3

あとは、どこで答えを決めるかです。葉に着いたときだけ、残りが 0 かどうかで答えます。葉でなければ、左の子か右の子のどちらかで見つかれば true です。子が無い側は空の木なので、false が返ってきます。

ここから​解答です。​先に​自分で​書いてから​読むと、​考え方が​残ります。

解答

Python

Python

def has_path_sum(root, target):
    if root is None:
        return False
    target -= root.val
    left = root.left
    right = root.right
    if left is None:
        if right is None:
            return target == 0
    found = has_path_sum(
        left, target
    )
    if found:
        return True
    return has_path_sum(
        right, target
    )

JavaScript

JavaScript

function hasPathSum(
  root, target
) {
  if (root === null) {
    return false;
  }
  target -= root.val;
  const { left, right } = root;
  if (left === null) {
    if (right === null) {
      return target === 0;
    }
  }
  const found = hasPathSum(
    left, target
  );
  if (found) {
    return true;
  }
  return hasPathSum(
    right, target
  );
}

左の子で見つかれば、すぐ True (JavaScript では true) を返すので、右の子は調べずに戻ります。見つかった時点で、それ以上たどらずに済みます。

計算量

  • 時間は O(n) です。どの節にも多くて 1 回ずつ行きます
  • 使う記憶は O(h) です。h は木の高さで、再帰の呼び出しが根から葉までの深さの分だけ積み重なります
  • 木が 1 本道に偏ると h は n と同じになり、記憶は O(n) です

よくある間違い

  • 合計が目標を超えたら打ち切る。値に負の数があるので、超えたあとに減って目標へ戻ることがあります。例 2 では 4 と 3 で 7 になっても、次の -2 で 5 に届きます。正の数だけと決まっていない限り、途中では打ち切れません
  • 葉でない節で答えを決める。残りが 0 になった時点で true を返すと、まだ子がある節で止めてしまいます。例 3 では根の 1 で残りが 0 になりますが、根は葉ではないので答えは false です
  • 子が 1 つだけの節を葉と思う。「左の子が無いから終わり」としてしまうと、右にだけ続く道を見落とします。葉は、左も右も無い節だけです

面接での話し方の例

書き始める前に、方針を短く口に出します。

「道を全部書き出さなくても、残りの数を子へ渡していけば足ります。葉に着いたときだけ、残りが 0 かどうかで答えます。値に負の数があるので、途中で目標を超えても打ち切りません。時間は O(n)、記憶は木の高さの分です。」

書き終えたら、例を 1 つ手でたどって見せます。

「例 2 でたどります。根の 4 で残りは 1、次の 3 で残りは -2 になり、目標を超えています。ここで打ち切らずに進むと、葉の -2 で残りが 0 になるので true です。負の数があるときに打ち切ってはいけない理由が、この例で分かります。」

解答を動かした版 Python 3.12.14Node.js 22.23.4確認日 2026年10月24日

コーディング面接問題の一覧へ戻る