Spiral Matrix II Algorithm

TypeScript実装の詳細解析

🎯 アルゴリズム概要

基本戦略

  • • 4つの境界(top, bottom, left, right)を管理
  • • 螺旋の方向に沿って順番に埋める
  • • 各方向完了後、境界を内側に移動

計算量

時間: O(n²)
空間: O(n²)

🔄 処理ステップの可視化

ステップ1: 右方向

1
2
3
0
0
0
0
0
0

上の行を左から右へ埋める

ステップ2: 下方向

1
2
3
0
0
4
0
0
5

右の列を上から下へ埋める

ステップ3: 左方向

1
2
3
0
0
4
7
6
5

下の行を右から左へ埋める

ステップ4: 上方向

1
2
3
8
9
4
7
6
5

左の列を下から上へ、中央を埋める

💻 TypeScript実装

spiral-matrix.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
* 螺旋状にn×nマトリックスを1からn²まで埋める関数
* @param n - マトリックスのサイズ (1 <= n <= 20)
* @returns 螺旋状に埋められたn×nマトリックス
*/
function generateMatrix(n: number): number[][] {
// n×nマトリックスを0で初期化
const matrix: number[][] = Array(n).fill(null).map(() => Array(n).fill(0));
let top: number = 0, bottom: number = n - 1, left: number = 0, right: number = n - 1;
let num: number = 1;
while (top <= bottom && left <= right) {
// 上の行を左から右へ
for (let col: number = left; col <= right; col++) {
matrix[top][col] = num++;
}
top++;
// 右の列を上から下へ
for (let row: number = top; row <= bottom; row++) {
matrix[row][right] = num++;
}
right--;
// 下の行を右から左へ(行が残っている場合)
if (top <= bottom) {
for (let col: number = right; col >= left; col--) {
matrix[bottom][col] = num++;
}
bottom--;
}
// 左の列を下から上へ(列が残っている場合)
if (left <= right) {
for (let row: number = bottom; row >= top; row--) {
matrix[row][left] = num++;
}
left++;
}
}
return matrix;
}
export { generateMatrix };

🎮 インタラクティブデモ

1 3 6

📊 処理解析

⏱️ 時間計算量

O(n²) 各要素を一度だけ訪問

• 外側ループ: 最大 ⌈n/2⌉ 回
• 内側ループ: 各境界に沿って移動
• 総訪問回数: n² 回(すべての要素)

💾 空間計算量

O(n²) 結果マトリックスのみ

• 結果マトリックス: n² 要素
• 追加変数: O(1) (境界変数のみ)
• 最適化: 不要な配列生成を回避

🔍 詳細ステップ解析

ステップ1: 右方向への移動

// 上の行を左から右へ
for (let col: number = left; col <= right; col++) {
    matrix[top][col] = num++;
}
top++;

処理内容:

  • • 現在のtop行の左端から右端まで数値を配置
  • • numを1ずつ増加させながら設定
  • • 処理完了後、top境界を1つ下に移動

ステップ2: 下方向への移動

// 右の列を上から下へ
for (let row: number = top; row <= bottom; row++) {
    matrix[row][right] = num++;
}
right--;

処理内容:

  • • 現在のright列の上端から下端まで数値を配置
  • • 更新されたtop位置から開始
  • • 処理完了後、right境界を1つ左に移動

ステップ3: 左方向への移動

if (top <= bottom) {
    for (let col: number = right; col >= left; col--) {
        matrix[bottom][col] = num++;
    }
    bottom--;
}

処理内容:

  • • 行が残っている場合のみ実行
  • • bottom行の右端から左端まで数値を配置
  • • 処理完了後、bottom境界を1つ上に移動

ステップ4: 上方向への移動

if (left <= right) {
    for (let row: number = bottom; row >= top; row--) {
        matrix[row][left] = num++;
    }
    left++;
}

処理内容:

  • • 列が残っている場合のみ実行
  • • left列の下端から上端まで数値を配置
  • • 処理完了後、left境界を1つ右に移動

⚡ パフォーマンス最適化

メモリ効率

  • Array.fill(null)で型安全な初期化
  • • 不要なオブジェクト生成を回避
  • • プリミティブ型のみ使用

処理効率

  • • 境界チェックで無駄な処理を回避
  • • 単一パスでマトリックス完成
  • • キャッシュ効率的なアクセスパターン

LeetCode対応

  • • 制約範囲での最適性能
  • • TypeScript 5.1互換
  • • Node.js 18.16.1対応