1. 程式人生 > 實用技巧 >N皇后

N皇后

遞歸回溯法

function putNQueen(n) {
    let res = []; //最終存放結果的陣列
    // 核心依賴倆引數 rowIndex,當前想嘗試在第幾行上放皇后
    // prev 上一次存放皇后的結果,初始值為 [],放的是對應的列值

    // 三個陣列,已放過的列的值、左斜 rowIndex + columnIndex、右斜對角線線的是否放過 rowIndex - columnIndex
    let hasPutColumnArr = [];
    let leftCorner = [];
    let rightCorner = [];

    const record = (rowIndex, columnIndex, bool) => {
        hasPutColumnArr[columnIndex] = bool;
        leftCorner[rowIndex - columnIndex] = bool;
        rightCorner[rowIndex + columnIndex] = bool;
    };
    // 嘗試在第n行中擺放皇后的位置
    const putQueen = (rowIndex, prev) => {
        console.log(rowIndex, prev);
        if (rowIndex === n) {
            return res.push(prev);
        }
        for (let columnIndex = 0; columnIndex < n; columnIndex++) {
            const freeColumn = !hasPutColumnArr[columnIndex];
            const freeLeftCorner = !leftCorner[rowIndex + columnIndex];
            const freeRightCorner = !leftCorner[rowIndex - columnIndex];
            // 可放置,則繼續遞迴
            if (freeColumn && freeLeftCorner && freeRightCorner) {
                // 記錄當前行列為已放皇后
                record(rowIndex, columnIndex, true);
                // 注意這裡prev.concat不會影響出棧後prev的值,prev.concat返回的是拼接後新的值
                // 注意這裡如果用是prev.push,第一傳進去的push的item,第二會影響後續prev的值
                putQueen(rowIndex + 1, prev.concat(columnIndex));
                // 出棧後將皇后置為未放狀態
                record(rowIndex, columnIndex, false);
            }
        }
    };
    putQueen(0, []);
    return res;
}