52. N-Queens II

Problem


Tags: Backtracking

The n-queens puzzle is the problem of placing n queens on an n x n chessboard such that no two queens attack each other.

Given an integer n, return the number of distinct solutions to the n-queens puzzle.

Example 1:

Input: n = 4
Output: 2
Explanation: There are two distinct solutions to the 4-queens puzzle as shown.

Example 2:

Input: n = 1
Output: 1

Constraints:

  • 1 <= n <= 9

Code

GO

// 52. N-Queens II (2/19/53378)
// Runtime: 0 ms (91.59%) Memory: 1.92 MB (39.25%) 

import "fmt"

var result int
var queens_col [9]int
var n int

func abs(a int) int {
	if a < 0 {
		return -a
	} else {
		return a
	}
}

func attacked(row int, col int) bool {
	for i := 0; i < row; i++ {
		enemy_row, enemy_col := i, queens_col[i]
		relative_x, relative_y := abs(enemy_row-row), abs(enemy_col-col)

		if relative_x == relative_y || col == enemy_col {
			return true
		}
	}
	return false
}

func place_queen(row int) {
	if row == n {
		result++
	}

	for i := 0; i < n; i++ {
        if !attacked(row, i) {
			queens_col[row] = i
			place_queen(row + 1)
			queens_col[row] = -1
		}
	}
}

func totalNQueens(sn int) int {
    result = 0
    queens_col = [9]int{-1,-1,-1,-1,-1,-1,-1,-1,-1}
    n = sn

	place_queen(0)

	return result
}

JS

// 52. N-Queens II (1/14/53378)
// Runtime: 76 ms (72.13%) Memory: 38.63 MB (94.43%) 

/**
 * @param {number} n
 * @return {number}
 */
var totalNQueens = function (n) {
    // 這一題有個特點,就是他 n 只有 1 ~ 9 ,所以用 testcase 跑完就可以知道答案了 XD
    // return [1, 0, 0, 2, 10, 4, 40, 92, 352][n - 1];

    // 正確的方法是用遞迴跑完所有結果

    // 可行方法數
    let result = 0;

    // 皇后所在的行數
    const queens_col = Array(n).fill(-1);

    function valid(row, col) {
        // 確認該格是否可放
        for (let i = 0; i < row; i++) {
            // 第 i 列皇后位置
            const prev_row = i;
            const prev_col = queens_col[i];

            const relative_x = Math.abs(prev_row - row);
            const relative_y = Math.abs(prev_col - col);

            // relative_x === relative_y: 位於已放皇后之斜線上, prev_col === col: 位於已放皇后之同行
            if (relative_x === relative_y || prev_col === col) return false;
        }
        return true;
    }

    function place_queen(row) {
        // 最後一列可行的話(最深遞迴),可行方法數 += 1
        if (row === n) result++;

        for (let col = 0; col < n; col++) {
            // 去跑每行
            if (valid(row, col)) {
                // 如果那行可以放就放,然後找放這行接下來的可能性
                queens_col[row] = col;
                place_queen(row + 1);
                // 找完放這行的可能性之後要清掉,要不然下個 validation 可能會錯
                queens_col[row] = -1;
            }
        }
    }

    // 從第一列開始放皇后
    place_queen(0);

    return result;
};