再帰的深さ優先探索による O(N) 実装
LeetCode 2625 - 多次元配列を指定深度まで平坦化するアルゴリズム
多次元配列
arr と深さ
n
を受け取り、指定された深さまで平坦化した配列を返します。平坦化は現在のネスト深度が
n
未満の場合にのみ実行されます。最初の配列の要素は深度 0 とみなされます。
Example 1:
入力: arr = [1, 2, 3, [4, 5, 6], [7, 8, [9, 10, 11], 12], [13, 14, 15]], n = 0
出力: [1, 2, 3, [4, 5, 6], [7, 8, [9, 10, 11], 12], [13, 14, 15]]
説明: n=0 の場合、平坦化されません
Example 2:
入力: arr = [1, 2, 3, [4, 5, 6], [7, 8, [9, 10, 11], 12], [13, 14, 15]], n = 1
出力: [1, 2, 3, 4, 5, 6, 7, 8, [9, 10, 11], 12, 13, 14, 15]
説明: 深度0のサブ配列のみ平坦化されます
🚀 Runtime: 80ms (84.88%) | Memory: 76.02MB (85.12%)
type MultiDimensionalArray = (number | MultiDimensionalArray)[];
/**
* 多次元配列を指定された深さまで平坦化する
*
* @param arr - 平坦化する多次元配列
* @param n - 平坦化する深さ(0の場合は平坦化しない)
* @returns 平坦化された配列
*
* @complexity
* Time: O(N) - N は全要素数
* Space: O(N + D) - N は結果配列、D はコールスタック深度
*
* @example
* flat([1, 2, [3, 4]], 1) // [1, 2, 3, 4]
* flat([1, [2, [3]]], 1) // [1, 2, [3]]
*/
var flat = function (arr: MultiDimensionalArray, n: number): MultiDimensionalArray {
// 結果配列を初期化(クロージャで共有)
const result: MultiDimensionalArray = [];
/**
* 内部再帰関数:配列を深さ制限付きで平坦化
* @param items - 処理対象の配列
* @param depth - 残りの平坦化可能深度
*/
function flatten(items: MultiDimensionalArray, depth: number): void {
for (const item of items) {
// 配列かつ深度制限内の場合、再帰的に展開
if (Array.isArray(item) && depth > 0) {
flatten(item, depth - 1);
} else {
// プリミティブまたは深度制限到達の配列をそのまま追加
result.push(item);
}
}
}
// 初期呼び出し
flatten(arr, n);
return result;
};
外部でresultを宣言し、内部関数から参照することで配列の再生成を回避
再帰型定義により任意深度の配列を表現し、コンパイル時に型エラーを検出
元の配列を変更せず、新しい結果配列を構築するPure function
n=0、空配列、深い入れ子などを正しく処理
初期化:結果配列を空配列で初期化し、内部flatten関数を定義します
ループ処理:各要素についてループで走査します(for...of)
分岐判定:配列かつdepth > 0の場合は再帰的に展開、そうでなければ直接追加
ループバック:紫の破線矢印は次の要素への遷移を示します
完了:すべての要素を処理後、結果配列を返して終了します
O(N)
N = 配列内の全要素数(プリミティブ値 + サブ配列の総数)
各要素を1回ずつ訪問し、配列判定とpush()はO(1)のため全体でO(N)
O(N + D)
結果配列: O(N) - 全要素を格納
コールスタック: O(D) - 最大深度までの再帰呼び出し(D ≤ 1000)
| 実装方式 | 時間計算量 | 空間計算量 | 可読性 | 性能(実測) |
|---|---|---|---|---|
| 最適化再帰版(推奨) | O(N) | O(N + D) | ★★★★★ | 80ms (84.88%) |
| スプレッド再帰版 | O(N) | O(N + D) | ★★★★☆ | 156ms (38.84%) |
| reduce版 | O(N²) | O(N² + D) | ★★★☆☆ | TLE |
| スタック反復版 | O(N) | O(N + D) | ★★★☆☆ | 100ms (73.26%) |
...は大規模配列で非効率(内部コピーのコスト)
concat()は毎回新配列を生成しO(N²)に劣化