The n-queens puzzle is the problem of placing n queens on an n×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:
Input: 4 Output: 2 Explanation: There are two distinct solutions to the 4-queens puzzle as shown below. [ [".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", // Solution 2 "Q...", "...Q", ".Q.."] ]
51. N-Queens N 的变形,这道题只需要给出不同解法的数量,比51题要简单一些。
解法:回溯Backtracking
Java:
/** * don't need to actually place the queen, * instead, for each row, try to place without violation on * col/ diagonal1/ diagnol2. * trick: to detect whether 2 positions sit on the same diagnol: * if delta(col, row) equals, same diagnol1; * if sum(col, row) equals, same diagnal2. */ private final Set<Integer> occupiedCols = new HashSet<Integer>(); private final Set<Integer> occupiedDiag1s = new HashSet<Integer>(); private final Set<Integer> occupiedDiag2s = new HashSet<Integer>(); public int totalNQueens(int n) { return totalNQueensHelper(0, 0, n); } private int totalNQueensHelper(int row, int count, int n) { for (int col = 0; col < n; col++) { if (occupiedCols.contains(col)) continue; int diag1 = row - col; if (occupiedDiag1s.contains(diag1)) continue; int diag2 = row + col; if (occupiedDiag2s.contains(diag2)) continue; // we can now place a queen here if (row == n-1) count++; else { occupiedCols.add(col); occupiedDiag1s.add(diag1); occupiedDiag2s.add(diag2); count = totalNQueensHelper(row+1, count, n); // recover occupiedCols.remove(col); occupiedDiag1s.remove(diag1); occupiedDiag2s.remove(diag2); } } return count; }
Python:
# quick solution for checking if it is diagonally legal class Solution: # @return an integer def totalNQueens(self, n): self.cols = [False] * n self.main_diag = [False] * (2 * n) self.anti_diag = [False] * (2 * n) return self.totalNQueensRecu([], 0, n) def totalNQueensRecu(self, solution, row, n): if row == n: return 1 result = 0 for i in xrange(n): if not self.cols[i] and not self.main_diag[row + i] and not self.anti_diag[row - i + n]: self.cols[i] = self.main_diag[row + i] = self.anti_diag[row - i + n] = True result += self.totalNQueensRecu(solution + [i], row + 1, n) self.cols[i] = self.main_diag[row + i] = self.anti_diag[row - i + n] = False return result
Python:
# slower solution class Solution: # @return an integer def totalNQueens(self, n): return self.totalNQueensRecu([], 0, n) def totalNQueensRecu(self, solution, row, n): if row == n: return 1 result = 0 for i in xrange(n): if i not in solution and reduce(lambda acc, j: abs(row - j) != abs(i - solution[j]) and acc, xrange(len(solution)), True): result += self.totalNQueensRecu(solution + [i], row + 1, n) return result
C++:
class Solution { public: int totalNQueens(int n) { int res = 0; vector<int> pos(n, -1); totalNQueensDFS(pos, 0, res); return res; } void totalNQueensDFS(vector<int> &pos, int row, int &res) { int n = pos.size(); if (row == n) ++res; else { for (int col = 0; col < n; ++col) { if (isValid(pos, row, col)) { pos[row] = col; totalNQueensDFS(pos, row + 1, res); pos[row] = -1; } } } } bool isValid(vector<int> &pos, int row, int col) { for (int i = 0; i < row; ++i) { if (col == pos[i] || abs(row - i) == abs(col - pos[i])) { return false; } } return true; } };
类似题目: