再帰で二分木の高さが釣り合っているか確かめる

二分木の​どの​節でも、​左と​右の​高さの​差が​ 1 以下かを​返します。​下から​高さを​返し、​崩れを​見つけたら​印を​返して​止める、​木の​再帰の​練習です。

海外で定番の問題リスト 4 本のうち 2 本に入っています (NeetCode 150、Grind 75)

問題

二分木の根 root を受け取ります。この木のどの節でも、左の部分木の高さと右の部分木の高さの差が 1 以下なら真、1 つでも 2 以上の差がある節があれば偽を返す関数を書いてください。

  • 高さは、その部分木の根からいちばん深い節までの節の数です。空の部分木の高さは 0 です
  • 根だけでなく、すべての節で差を確かめます
  • 各節は val (値)、left (左の子)、right (右の子) を持ちます。子が無いところは、Python では None、JavaScript では null、Go では nil です。Go の節は TreeNode で、Val、Left、Right と大文字で始まります
  • 木が空のときは真を返します
  • 節の数は 0 以上 500 以下、値はどれも -100 以上 100 以下です

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

入力と出力の例

例 1

根が 7、その下が 3 と 9 です。3 には右の子 5、9 には左の子 8 があります。どの節も左右の高さの差は 1 以下です。

入力

root = [7, 3, 9, null, 5, 8]

出力

true

例 2

根の 6 では、左の高さ 3 と右の高さ 2 で差は 1 です。ところが 4 の節では、左に 2 と 1 が 2 段ぶら下がり、右は空なので差が 2 になります。

入力

root = [6, 4, 8, 2, null, null,
  9, 1]

出力

false

例 3

空の木です。崩れている節が無いので真です。

入力

root = []

出力

true

面接での聞かれ方

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

  • 「この二分木の高さが釣り合っているかを判定してください」
  • 根だけを比べる書き方を出すと、例 2 のような木を示して「これはどうなりますか?」と聞かれます
  • 書き終えたあとに「高さを何回数えていますか? 1 回のたどりにできますか?」と、計算量を詰めるよう聞かれます

「釣り合い」の決め方 (差が 1 以下、すべての節で) を最初に確かめて口に出しておきます。

アルゴリズムのチートシートの「再帰と木」に、​この​型の​要点を​表と​コードで​まとめています。

main.py
def is_balanced(root):
    # root の節は val、left、right を持ちます。空きは None です
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
# build_tree は、例と同じ並びから木を組みます
print(is_balanced(build_tree([7, 3, 9, None, 5, 8])))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します