1. [1,2,3,null,4] -> true
  2. [1] -> true
  3. 完全二分木 [1..7] -> true
  4. [1,2,null,3] (左に偏り 高さ差 2) -> false
  5. [1,null,2,null,null,null,3] (右に一直線 高さ差 0 → 偏りなし each step) -> false
  6. [1,2,3,4,null,null,null,5] (深い左) -> false
コース一覧
コンピューターサイエンス上級:アルゴリズムとデータ構造
二分木の平衡判定

コンピューターサイエンス上級:アルゴリズムとデータ構造

探索、ソート、木、グラフ、動的計画法、貪欲法など、競技プログラミングや技術面接で問われる高度なアルゴリズムとデータ構造を学べるコースです。基本的な CS の知識を持ち、アルゴリズム力を伸ばしたい学習者や、外資・大手の技術面接対策をしたい方を対象としています。約 13 時間 (1 日 30 分 × 26 日) で 50 レッスンを修了でき、修了後はコーディング面接の実装問題を構造的に解けるようになります。

1
連結リスト
01. リンクリスト構築と長さの計算5分
02. リンクリストの反転5分
03. リンクリストのサイクル検出5分
04. ソート済みリンクリストの merge5分
05. リンクリストの中央ノード取得5分
06. ソート済みリストの重複削除5分
07. 第1章まとめクイズ5分
2
二分木
01. 二分木の in-order 走査5分
02. 二分木の pre-order 走査5分
03. 二分木の post-order 走査5分
04. 二分木の幅優先走査 (BFS)5分
05. 二分木の高さ5分
06. 二分木の平衡判定5分
07. 第2章まとめクイズ — 二分木5分
3
探索木 (BST)
01. BST に値を挿入する5分
02. BST から値を検索する5分
03. BST の最小値と最大値5分
04. BST 妥当性チェック5分
05. BST で k 番目に小さい値5分
06. BST から値を削除する5分
07. 第 3 章 まとめクイズ5分
4
ハッシュとセット
01. hashmap で頻度集計5分
02. キーでグループ化5分
03. two sum (hash で O(n))5分
04. 部分配列の和 = k の個数5分
05. 最長連続部分列5分
06. 集合の積 (intersection)5分
07. 第4章まとめクイズ5分
5
グラフ
01. グラフ BFS で連結成分サイズを求める5分
02. グラフ DFS で連結成分の数を数える5分
03. グラフのパス存在判定5分
04. BFS で最短経路の長さを求める5分
05. トポロジカルソート5分
06. 2 部グラフ判定5分
07. ダイクストラ法 — 重み付きグラフの最短経路15分
08. 第5章まとめクイズ — グラフ5分
6
動的計画法 (上級)
01. 編集距離 (レーベンシュタイン距離)5分
02. 最長増加部分列(LIS)の解法 ── AOJ 2430 対応の動的計画法5分
03. 最大部分配列和 (Kadane)5分
04. 隣り合わない最大値 (House Robber)5分
05. グリッド経路数 (Unique Paths)5分
06. 単語分割可能か (Word Break)5分
07. 第6章まとめクイズ — 動的計画法 (上級)5分
7
総合データ構造と関数型
01. map と filter を組み合わせる5分
02. reduce で積を計算5分
03. 関数合成5分
04. カリー化5分
05. trie の単純検索 (prefix マッチ)5分
06. Union-Find (連結成分数)5分
07. 最終総まとめクイズ5分

二分木の平衡判定

木が平衡している、とは「どのノードで見ても、左の高さと右の高さの差が 1 以下」という状態です。根だけ見て済む話ではありません。

根では釣り合って見えても、下で崩れている

根の左右が同じ高さでも、左の枝のさらに奥で片側だけ 3 段伸びていれば、そこは平衡ではありません。判定の対象は全ノードです。1 か所でも差が 2 以上あれば、木全体として不合格になります。

1 の左に 2、その 2 の左に 3 だけがつながった木で考えてみます。根から見ると左の高さは 2、右は 0 で、差は 2。この 1 か所だけで木全体が不合格です。

なぜそこまで気にするのかというと、崩れた木は前のレッスンで見たとおり段数が伸びるからです。データベースの索引が挿入のたびに形を整え直しているのは、放っておくと入ってくる順番次第で木が簡単に一直線へ育つためです。

全ノードで測ると、同じ場所を何度も測り直す

素直に書くと、あるノードで左右の高さを測り、それから子へ降りて同じことを繰り返す形になります。ところがこれは、上のほうほど無駄が大きくなります。根で全体を測り、次に左の子でその中身をもう一度測り、その子でまた測る。深いところの葉は、段数の分だけ繰り返し歩かれます。

高さは 1 回測れば足りるはずです。下から持ち上がってくる途中で判定も済ませてしまえば、木全体を 1 度歩くだけで終わります。

測りながら、壊れた時点で打ち切る

戻り値に、測った値とは別の意味を持つ番人を混ぜます。フォルダの合計容量を出しつつ、壊れたファイルが 1 つでもあれば集計をやめる、という例で見てみます。

Python

def total_size(node): if node is None: return 0 if node.broken: return -1 # 番人 left = total_size(node.left) if left == -1: return -1 # 見つけたら、そのまま上へ渡す right = total_size(node.right) if right == -1: return -1 return node.size + left + right

容量は必ず 0 以上なので、-1 は「壊れていた」以外の意味を持ちません。だから戻り値 1 つで、測った結果と異常の有無を同時に運べます。

左で見つけた時点で右へは降りません。呼び出した側も同じことをするので、異常は根まで一気に伝わり、途中の集計は 1 回も走りません。全部歩いてから最後に判定する書き方と比べて、無駄が消えます。

平衡判定も同じ形にできます。高さは必ず 0 以上と決まっているので、番人には負の値が使えます。左右から返ってきた値を見て、番人ならそのまま上へ渡す。番人でなければ差を確かめて、大丈夫なら高さを、駄目なら番人を返す。これで 1 度歩くだけで全ノードの判定が終わります。

戻り値が 2 つの意味を持つので、呼び出した直後の確認を飛ばすと壊れます。左を確かめずに右へ降りると、打ち切りの効果が消えるうえ、番人の値をそのまま高さとして計算してしまいます。

要件

  1. tree は BFS 順の配列で、null (Python では None) は欠損ノードを表す
  2. 全ノードで左右部分木の高さの差が 1 以下なら true を返す
  3. 空の木 ([]) や [null] は true として扱う

入出力例

isBalanced([1,2,3,null,4]) → true isBalanced([1]) → true isBalanced([1,2,3,4,5,6,7]) → true isBalanced([1,2,null,3]) → false isBalanced([1,null,2,null,null,null,3]) → false isBalanced([1,2,3,4,null,null,null,5]) → false

ヒント

素朴な実装は各ノードで height() を計算する O(n^2) になる

O(n) に落とすには、再帰の戻り値に高さを返しつつ、unbalanced を見つけたら -1 などのセンチネル値を返して伝播させる

abs(left - right) > 1 のチェックを忘れず、絶対値で比較する

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

関連レッスン

  • 第2章まとめクイズ — 二分木

    二分木の走査 (in-order / pre-order / post-order / BFS) と高さ・平衡判定について理解度を確認する。

  • BST に値を挿入する

    二分探索木 (BST) に新しい値を挿入し、挿入後の in-order 走査結果を配列で返す関数を実装する。

  • hashmap で頻度集計

    配列の各要素が何回現れたかを `hashmap` で集計し、最も多く出た値を返す関数を実装する。

  • グラフ BFS で連結成分サイズを求める

    幅優先探索 (BFS) を使って、指定した頂点を含む連結成分のノード数を返す関数を実装する。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • データベースデータを構造化して保存する仕組み
  • 戻り値呼び出し元への返答を表す点線矢印
  • treeディレクトリ構造をツリー表示するコマンド
  • 配列サイズ固定の同型データの集まり
  • None「値がない」ことを表す特別な値。
main.py
学習モード
エディタを読み込んでいます

メモ

二分木の平衡判定

⌘S で保存