1. 空木 -> -1
  2. [10] k=1 -> 10
  3. [10] k=2 -> -1 (範囲外)
  4. [10,5,15,3,7,null,20] k=1 -> 3
  5. [10,5,15,3,7,null,20] k=4 -> 10
  6. [10,5,15,3,7,null,20] k=6 -> 20
  7. [10,5,15,3,7,null,20] k=0 -> -1
コース一覧
コンピューターサイエンス上級:アルゴリズムとデータ構造
BST で k 番目に小さい値

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

探索、ソート、木、グラフ、動的計画法、貪欲法など、競技プログラミングや技術面接で問われる高度なアルゴリズムとデータ構造を学べるコースです。基本的な 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分

BST で k 番目に小さい値

1 番小さい値が欲しいだけなのに、全部を並べている

k 番目に小さい値を返す。そう言われて最初に浮かぶのは「全部取り出して並べ、k - 1 番目を見る」でしょう。答えは合います。ただ、ノードが 100 万個ある木から 1 番目が欲しいときも、100 万個を配列に詰めてから先頭を見ることになります。

欲しいのは 1 個です。100 万個ぶんの置き場所を用意する必要はありません。

数えながら進んで、k 個目で止める

やることは、順番に見ながら数え、k 個目に当たったらそこで打ち切るだけです。木から離れて、ただの配列で形を見ておきます。

JavaScript

// 別題材 — ログの中から 3 件目の ERROR を返す let count = 0; for (const line of lines) { if (!line.startsWith("ERROR")) continue; count += 1; if (count === 3) return line; } return null;

数える変数を 1 つ外に置き、当たったらその場で返す。この形をそのまま木へ移します。違うのは「順番に見る」の中身だけです。

ここで気をつけるのは、数える変数の置き場所です。走査の中で作ると、呼ばれるたびに 0 へ戻ってしまいます。走査の外側に 1 つだけ置いて、どの呼び出しからも同じ数を触るようにしてください。Python で外側の変数を書き換えるときは nonlocal の宣言が要ります。

小さい順に見て回る道は決まっている

木のノードを小さい順に取り出す走査は、第 2 章で書いたものがそのまま使えます。左をすべて見てから自分、それから右です。次の木なら 3, 5, 7, 10, 15, 20 の順で出てきます。

diagram (will load when visible)

この順番が、そのまま小さいほうからの順位になります。k = 1 なら 3、k = 4 なら 10、k = 6 なら 20 です。数を増やす場所は「左から戻ってきて、自分の値を見たとき」の 1 か所だけです。降りる前に数えたり、右へ進んだ後に数えたりすると、順位がまるごとずれます。

k = 1 だけが欲しいなら、左端に着いた時点で終わります。100 万個の木でも、降りた回数ぶんしか触りません。

止めたつもりで、止まっていない

打ち切りでつまずくのは、答えが決まった後も走査が続いてしまう形です。再帰の中で答えを見つけて戻っても、呼び出し元はその先の右側へ進んでいきます。戻った先が「もう終わったこと」を知らないからです。答えが決まったかどうかを表す印を 1 つ持ち、次へ進む前にそれを見てください。

順位の数え方もずれやすいところです。k = 1 が最小値で、0 番目はありません。k が 0 以下のときと、ノードの数より大きいときは -1 を返す約束です。木を最後まで見終わっても数が届かなかった、という状態をきちんと返り値に落としてください。

解説

k 番目に大きい値を聞かれたときは、右から先に見て同じように数えるだけです。作り直しは要りません。

要件

  1. in-order 走査が昇順になる BST の性質を利用する
  2. k は 1 始まりの順位。1 番目 = 最小値
  3. k が範囲外、または空木の場合は -1 を返す

入出力例

bstKthSmallest([], 1) → -1 bstKthSmallest([10], 1) → 10 bstKthSmallest([10], 2) → -1 bstKthSmallest([10,5,15,3,7,null,20], 1) → 3 bstKthSmallest([10,5,15,3,7,null,20], 4) → 10 bstKthSmallest([10,5,15,3,7,null,20], 6) → 20 bstKthSmallest([10,5,15,3,7,null,20], 0) → -1

ヒント

in-order で配列に詰めてから `out[k-1]` を返すのが最もシンプル

効率を求めるなら、走査中にカウンタを増やし、k に達したら早期打ち切り

k の境界条件 (0 以下や木のサイズ超え) を忘れずにチェック

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

関連レッスン

  • BST から値を削除する

    BST から指定の値を削除し、削除後の in-order 走査結果を配列で返す関数を実装する。

  • 第 3 章 まとめクイズ

    探索木 (BST) の挿入・検索・削除・妥当性チェックなど、第 3 章の要点を確認する 4 択クイズ。

  • hashmap で頻度集計

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

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

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

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

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

  • 配列サイズ固定の同型データの集まり
  • 変数データに名前をつけて参照する仕組み
  • 再帰関数が自分自身を呼び出す処理パターン
main.py
学習モード
エディタを読み込んでいます

メモ

BST で k 番目に小さい値

⌘S で保存