配列の逆順(再帰)
線形再帰パターンで分割統治の考え方を学び、両端から中央へ向かう処理を理解しよう
O(n)
時間計算量(線形)
O(n)
空間計算量
初級〜中級
難易度
線形再帰
手法
🔄 実行設定
現在の配列:
[1, 2, 3, 4, 5]
配列長:5要素
予想交換回数:2回
予想実行時間:< 1ms
📚 推奨配列
📊 統計情報
交換回数: 2回
最大深度: 2
再帰呼び出し: 3回
時間計算量: O(5)
🔄 反復実装との比較
反復結果: [5, 4, 3, 2, 1]
再帰: 教育的、反復: 実用的
🔄
アルゴリズムを実行してください
左側の設定パネルから配列を設定し、「配列逆順実行」ボタンを押してください
💻 実装例(JavaScript)
function reverseArray(array, start = 0, end = array.length - 1) {
// ベースケース:start >= end なら処理終了
if (start >= end) {
return;
}
// 両端の要素を交換
const temp = array[start];
array[start] = array[end];
array[end] = temp;
// 内側の範囲に対して再帰呼び出し
reverseArray(array, start + 1, end - 1);
}
// 使用例
const numbers = [1, 2, 3, 4, 5];
console.log("逆順前:", numbers);
reverseArray(numbers);
console.log("逆順後:", numbers); // [5, 4, 3, 2, 1]
// より明示的な実装
function reverseArrayExplicit(array, start, end) {
console.log(`reverseArray(${start}, ${end}) 呼び出し`);
if (start >= end) {
console.log(`ベースケース: start=${start}, end=${end}`);
return;
}
console.log(`交換: array[${start}] ↔ array[${end}]`);
[array[start], array[end]] = [array[end], array[start]];
reverseArrayExplicit(array, start + 1, end - 1);
}
// 反復実装(比較用)
function reverseArrayIterative(array) {
let start = 0;
let end = array.length - 1;
while (start < end) {
[array[start], array[end]] = [array[end], array[start]];
start++;
end--;
}
}
// 関数型実装(副作用なし)
function reverseArrayFunctional(array) {
if (array.length <= 1) return array;
return [
array[array.length - 1],
...reverseArrayFunctional(array.slice(1, -1)),
array[0]
];
}
// 計算量分析
// 時間計算量: O(n) - n/2回の交換
// 空間計算量: O(n) - 再帰スタック
// 再帰の深さ: floor(n/2)
🔄 再帰 vs 反復 vs 関数型
再帰実装
- • 分割統治の考え方が直感的
- • 数学的定義に忠実
- • 教育的価値が高い
- • スタック使用量 O(n)
- • 関数型プログラミングと相性良
反復実装
- • メモリ効率が良い O(1)
- • スタックオーバーフロー回避
- • 実用的で高速
- • 理解が容易
- • 実装がシンプル
関数型実装
- • 副作用なし(純粋関数)
- • 元配列を変更しない
- • 関数合成に適している
- • テストしやすい
- • メモリ使用量は多い