N-Queens Algorithm Deep Analysis

バックトラッキングによるN-Queens問題の詳細解析と可視化

アルゴリズム概要

N-Queens問題は、N×Nのチェス盤上にN個のクイーンを、互いに攻撃し合わないように配置する問題です。この問題をバックトラッキング手法で解決します。

1. 初期化
空のN×Nチェス盤を作成し、制約チェック用のセット(列、対角線)を初期化
2. 行ごとの探索
各行で可能な列位置を試行し、制約違反がないかチェック
3. 制約チェック
同じ列、対角線上に他のクイーンがないか高速チェック
4. 配置・再帰
有効な位置にクイーンを配置し、次の行を再帰的に探索
5. バックトラック
解が見つからない場合、前の状態に戻って別の選択肢を試行

ソースコード解析

/**
 * N-Queens問題を解く関数
 * @param {number} n - チェス盤のサイズ (1 <= n <= 9)
 * @returns {string[][]} - 全ての有効なクイーン配置を返す
 * 
 * 時間計算量: O(N!) - バックトラッキングで全探索
 * 空間計算量: O(N^2 * 解の個数) - 盤面保存のため
 */
function solveNQueens(n: number): string[][] {
    const results: string[][] = [];
    
    // 現在の盤面を '.' で初期化
    const board: string[][] = Array.from({ length: n }, () => 
        Array(n).fill('.')
    );
    
    // 使用済みの列・対角線を記録する集合(O(1)チェックのため)
    const cols: Set = new Set();      // 同じ列
    const diag1: Set = new Set();     // 左上→右下 (row-col)
    const diag2: Set = new Set();     // 右上→左下 (row+col)
    
    /**
     * バックトラッキング探索
     * @param {number} row - 現在の行
     */
    function backtrack(row: number): void {
        // ベースケース: 全ての行にクイーンを配置完了
        if (row === n) {
            const solution: string[] = board.map(r => r.join(''));
            results.push(solution);
            return;
        }
        
        // 現在の行の各列を試行
        for (let col = 0; col < n; col++) {
            // 攻撃範囲チェック(O(1)時間)
            if (cols.has(col) || 
                diag1.has(row - col) || 
                diag2.has(row + col)) {
                continue; // 制約違反のためスキップ
            }
            
            // クイーンを配置
            board[row][col] = 'Q';
            cols.add(col);
            diag1.add(row - col);
            diag2.add(row + col);
            
            // 次の行を再帰探索
            backtrack(row + 1);
            
            // バックトラック: 状態を元に戻す
            board[row][col] = '.';
            cols.delete(col);
            diag1.delete(row - col);
            diag2.delete(row + col);
        }
    }
    
    backtrack(0); // 0行目から開始
    return results;
}

インタラクティブ可視化

チェス盤

現在の状態

行: 0

列: -

試行回数: 0

バックトラック回数: 0

制約状況

使用済み列: なし

対角線1: なし

対角線2: なし

計算量解析

項目 計算量 説明
時間計算量 O(N!) 最悪の場合、各行でN個の位置を試行する必要があり、実際はそれより少ない
空間計算量 O(N) 再帰スタック、制約セット、盤面配列で線形空間
制約チェック O(1) Setを使用することで定数時間での制約確認が可能
解の格納 O(N² × 解の個数) 各解をN×Nの文字列配列として保存
4
盤面サイズ (N)
2
解の総数
0
総操作回数
100%
効率性

重要な最適化ポイント

🚀 Set を使った高速制約チェック
cols, diag1, diag2 のSetを使用してO(1)時間での制約確認を実現。 従来のO(N)チェックから大幅に高速化。
📐 数学的対角線表現
対角線を (row - col)(row + col) で表現することで、 効率的な対角線制約管理が可能。
💾 メモリ効率的な状態管理
2次元配列ではなく1次元の制約セットで状態を管理し、 メモリ使用量を最小化。
⚡ 早期終了とプルーニング
制約違反を検出した瞬間に探索を打ち切り、 無駄な計算を回避する枝刈り最適化。