カタラン数の漸化式による O(n) / O(1) 実装
整数 n が与えられたとき、
1 から n
までの連続整数をすべて使って構成できる「構造的に異なる二分探索木(BST)」の個数を返す問題です。
Example 1:
Input: n = 3
Output: 5
解説: n=3 のとき、構造的に異なるBSTは5通り存在します。
Example 2:
Input: n = 1
Output: 1
1 <= n <= 19// で誤差なく計算
class Solution:
"""
Unique Binary Search Trees 問題を解くクラス。
カタラン数の漸化式を用いてO(n)/O(1)で計算。
"""
def numTrees(self, n: int) -> int:
"""
LeetCode用エントリポイント(競技プログラミング向け実装)。
Args:
n: ノード数 (1 <= n <= 19)
Returns:
構造的に異なるBSTの個数
Complexity:
Time: O(n)
Space: O(1)
"""
# カタラン数の漸化式: C_0 = 1
c: int = 1
# C_n = C_{n-1} * 2(2n - 1) / (n + 1)
for i in range(1, n + 1):
# 整数除算で誤差なく計算
c = c * 2 * (2 * i - 1) // (i + 1)
return c
フローの説明:
1. 初期化: c = 1 で開始(C₀の値)
2. ループ開始: i = 1 から n まで反復
3. 条件分岐: i <= n
であれば処理を続行、そうでなければ終了
4. 漸化式適用: c = c × 2(2i - 1) ÷ (i + 1) を計算
5. インクリメント: i を1増やす
6. ループバック: 条件分岐に戻る(紫の矢印)
7. 終了: ループ完了後、c を返す
| 項目 | 計算量 | 備考 |
|---|---|---|
| 時間 | O(n) | ループが n 回実行され、各ステップは定数時間 |
| 空間 | O(1) | 変数 c, i のみ使用(配列不要) |
| アプローチ | 時間 | 空間 | 備考 |
|---|---|---|---|
| 漸化式(本実装) | O(n) | O(1) | 最もシンプルで高速 |
| DP配列 | O(n²) | O(n) | 定義に忠実だが遅い |
| 再帰+メモ化 | O(n²) | O(n) | 関数呼び出しオーバーヘッド |