N-Queens
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 all distinct solutions to the
n-queens puzzle.
Each solution contains a distinct board configuration of the
n-queens' placement, where
'Q'
and
'.'
both indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
----------------------------------------------------------------------
Typical DFS. Set up 3 vector<bool>s to indicate conflict
Red is backslash
Blue is slash
Green is row
class Solution {
public:
void queens(vector<vector<string> > &ret,vector<bool> &slash, vector<bool> &backslash, vector<bool> &usedRow, vector<string> cur, int col, int n) {
if (col == n) {
ret.push_back(cur);
return;
}
for (int row = 0; row < n; row++) {
// check conflicts in diagonals and same row
if (slash[col + row] && backslash[row-col + n] && usedRow[row]) {
cur[row][col] = 'Q';
slash[col + row] = false;
backslash[row-col + n] = false;
usedRow[row] = false;
queens(ret,slash,backslash,usedRow,cur,col+1,n);
// backtrack
cur[row][col] = '.';
slash[col + row] = true;
backslash[row-col + n] = true;
usedRow[row] = true;
}
}
}
vector<vector<string> > solveNQueens(int n) {
vector<vector<string> > ret;
vector<bool> slash(n*2,true);
vector<bool> backslash(n*2,true);
vector<bool> usedRow(n,true);
// populate vectors
string str = "";
for (int i = 0; i < n; i++) {
char c = '.';
str += c;
}
vector<string> cur(n,str);
queens(ret,slash,backslash,usedRow,cur,0,n);
return ret;
}
};
Update Feb-10-2015
Using bit operation
class Solution {
public:
string getString(int n, int p) {
string s(n,'.');
s[p] = 'Q';
return s;
}
void queens(vector<vector<string> > &rt, vector<string> cur,int slash, int backSlash, int row, int n) {
int upperLimit = (1 << n) - 1;
if (row == upperLimit) {
rt.push_back(cur);
return;
}
int possiblePositions = upperLimit & (~(slash | backSlash | row));
int itr = possiblePositions;
int p = n - 1;
while (possiblePositions != 0) {
int rightMost = possiblePositions & (-possiblePositions);
if (itr & 1) {
string s = getString(n,p);
vector<string> temp = cur;
temp.push_back(s);
possiblePositions -= rightMost;
queens(rt,temp,(slash + rightMost) << 1,(backSlash + rightMost) >> 1,row + rightMost,n);
}
p--;
itr >>= 1;
}
}
vector<vector<string> > solveNQueens(int n) {
vector<vector<string> > rt;
vector<string> cur;
queens(rt,cur,0,0,0,n);
return rt;
}
};
Java, updated on Sep-8th-2018
O(n!)
T(n) = n * T(n - 1)
class Solution {
public List> solveNQueens(int n) {
boolean[] cols = new boolean[n];
boolean[] diag = new boolean[n * 2]; // row + col
boolean[] antiDiag = new boolean[n * 2]; // row - col + n - 1
List> rt = new ArrayList<>();
dfs(0, n, new ArrayList(), rt, cols, diag, antiDiag);
return rt;
}
private void dfs(int row, int n, List sofar, List> rt,
boolean[] cols, boolean[] diag, boolean[] antiDiag) {
if (row >= n) {
rt.add(sofar);
return;
}
String cur = "";
for (int i = 0; i < n; i++) {
if (!cols[i] && !diag[row + i] && !antiDiag[row - i + n - 1]) {
cols[i] = true;
diag[row + i] = true;
antiDiag[row - i + n - 1] = true;
String tmp = cur + "Q";
for (int j = i + 1; j < n; j++) tmp += ".";
List tmpSofar = new ArrayList<>(sofar);
tmpSofar.add(tmp);
dfs(row + 1, n, tmpSofar, rt, cols, diag, antiDiag);
cols[i] = false;
diag[row + i] = false;
antiDiag[row - i + n - 1] = false;
}
cur += ".";
}
}
}
N-Queens II
Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
---------------------------------------------------------------------
Solution #1 similar to previous problem
Note that
usedRow[row] should be checked first otherwise it exceeds OJ's time limit
class Solution {
public:
void queens(int &ret,vector<bool> &slash, vector<bool> &backslash, vector<bool> &usedRow, int col, int n) {
if (col == n) {
ret++;
return;
}
for (int row = 0; row < n; row++) {
if (usedRow[row] && slash[col + row] && backslash[row-col + n]) {
slash[col + row] = false;
backslash[row-col + n] = false;
usedRow[row] = false;
queens(ret,slash,backslash,usedRow,col+1,n);
// backtrack
slash[col + row] = true;
backslash[row-col + n] = true;
usedRow[row] = true;
}
}
}
int totalNQueens(int n) {
vector<bool> slash(n*2,true);
vector<bool> backslash(n*2,true);
vector<bool> usedRow(n,true);
int ret = 0;
queens(ret,slash,backslash,usedRow,0,n);
return ret;
}
};
Solution #2
http://www.matrix67.com/blog/archives/266
Update on Nov-13-2014
基本思路为DFS
~(row | slash | backSlash) 代表每行上的可放位置,当切入到下一行时,slash跟backSlash分别需要位移一位
possiblePosition 代表当前行所有可放入棋子的位置
rightMostOne 代表当前放入棋子的位置
拿一个例子走一遍代码,立即能明白此算法
class Solution {
public:
void bitOP(int &num, int row, int slash, int backSlash, int n) {
int upperLimit = (1 << n) - 1; // upperLimit has n of '1'
if (row == upperLimit) {
num++;
return;
}
int possiblePosition = upperLimit & (~(row | slash | backSlash)); // get posiible positions for queen in a row
while (possiblePosition != 0) {
int rightMostOne = possiblePosition & (-possiblePosition); // get the most right '1' as new queen's position
possiblePosition -= rightMostOne;
bitOP(num, row + rightMostOne, (slash + rightMostOne) << 1, (backSlash + rightMostOne) >> 1,n);
}
}
int totalNQueens(int n) {
int num = 0;
bitOP(num,0,0,0,n);
return num;
}
};
Spiral Matrix
Given a matrix of
m x
n elements (
m rows,
n columns), return all elements of the matrix in spiral order.
For example,
Given the following matrix:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
You should return
[1,2,3,6,9,8,7,4,5]
.
-----------------------------------------------------------
Similar to #59, Spiral Matrix II
start at the outer most layer
class Solution {
public:
void spiral (vector<vector<int> > &matrix, vector<int> &ret, int m, int n, int k) {
if (m <= 0 || n <= 0) {
return;
}
if (m == 1) {
for (int i = 0; i < n; i++) {
ret.push_back(matrix[k][k + i]);
}
return;
}
if (n == 1) {
for (int i = 0; i < m; i++) {
ret.push_back(matrix[k + i][k]);
}
return;
}
// going right
for (int i = 0; i < n - 1; i++) {
ret.push_back(matrix[k][i + k]);
}
// going down
for (int i = 0; i < m - 1; i++) {
ret.push_back(matrix[k + i][n - 1 + k]);
}
// going left
for (int i = 0; i < n - 1; i++ ) {
ret.push_back(matrix[m - 1 + k][n - 1 + k - i]);
}
// going up
for (int i = 0; i < m - 1; i++ ) {
ret.push_back(matrix[k + m - 1 - i][k]);
}
spiral(matrix,ret,m-2,n-2,k+1);
}
vector<int> spiralOrder(vector<vector<int> > &matrix) {
int m = matrix.size();
vector<int> ret;
if (m == 0) return ret;
int n = matrix[0].size();
spiral(matrix,ret,m,n,0);
return ret;
}
};