# Question

Formatted question description: https://leetcode.ca/all/51.html

51	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.."]
]


# Algorithm

The exhaustive method for the N-Queens problem involves trying all combinations of queen placements. At each step, we need to ensure that the new queen does not conflict with all the previous queens. If a conflict occurs, we must find a new position for the queen.

This logic is well-suited for recursion. We start by creating an nxn array, queens, and call a recursive function from row 0. In the recursive function, we first check if the current row number is equal to n:

• If it is, then all queens have been successfully placed and we can add the queens array to the result.
• Otherwise, we iterate over all the positions in the current row and for each position, we check if it conflicts with the previously placed queens using a helper function:
• We first verify if there is a conflict in the same column by iterating over all previous rows. If a queen is found in the same column, we return false.
• Then, we verify if there is a conflict in the diagonals. This involves some coordinate conversion.
• If there is no conflict, we can place the queen in the current position. After placing the new queen, we call the recursive function on the next row. It’s important to handle the return state after the recursion.

# Code

• 
public class N_Queens {

public class Solution {

List<String[]> list = new ArrayList<String[]>();

public List<String[]> solveNQueens(int n) {

if (n <= 0)     return list;

// index is row-number, place[index] is position of queen on that row
int[] place = new int[n];

dfs(n, 0, place);

return list;
}

public void dfs(int n, int currentRow, int[] place) {
if (currentRow == n) {
// save to list
saveToList(place);
return;
}

for (int i = 0; i < n; i++) {

if (isValid(i, currentRow, place)) {
place[currentRow] = i; // 1 meaning place queen
dfs(n, currentRow + 1, place);
place[currentRow] = i; // undo place queen
}
}
}

public boolean isValid(int currentRowPosition, int currentRow, int[] place) {
// check all previous rows
for (int i = 0; i < currentRow; i++) {
// if (place[i] == currentRowPosition || Math.abs(currentRow - i) == Math.abs(place[i] - currentRowPosition))
if (place[i] == currentRowPosition || currentRow - i == (int)Math.abs(place[i] - currentRowPosition))
return false;
}

return true;
}

public void saveToList(int[] place) {

int len = place.length;
String[] array = new String[len];

// construct string of n dots...
String row = "";
for(int i = 0; i < len; i++) {
row += ".";
}

for(int i = 0; i < len; i++) {
int rowPosition = place[i]; // at position place[i] on row i
array[i] = row.substring(0, rowPosition) + "Q" + row.substring(rowPosition + 1);
}

}
}

}


• // OJ: https://leetcode.com/problems/n-queens/
// Time: O(N!)
// Space: O(N^2)
class Solution {
vector<vector<string>> ans;
vector<string> B;
vector<bool> col, hill, dale;
int n;
void dfs(int i) {
if (i == n) {
ans.push_back(B);
return;
}
for (int j = 0; j < n; ++j) {
int h = i + j, d = i + n - 1 - j;
if (col[j] || hill[h] || dale[d]) continue;
col[j] = hill[h] = dale[d] = true;
B[i][j] = 'Q';
dfs(i + 1);
B[i][j] = '.';
col[j] = hill[h] = dale[d] = false;
}
}
public:
vector<vector<string>> solveNQueens(int n) {
this->n = n;
B.assign(n, string(n, '.'));
col.assign(n, false);
hill.assign(2 * n - 1, false);
dale.assign(2 * n - 1, false);
dfs(0);
return ans;
}
};

• class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
res = []
g = [['.'] * n for _ in range(n)]
col = [False] * n
dg = [False] * (2 * n)
udg = [False] * (2 * n)

def dfs(u):
if u == n:
res.append([''.join(item) for item in g])
return
for i in range(n):
if not col[i] and not dg[u + i] and not udg[n - u + i]:
g[u][i] = 'Q'
col[i] = dg[u + i] = udg[n - u + i] = True
dfs(u + 1)
g[u][i] = '.'
col[i] = dg[u + i] = udg[n - u + i] = False

dfs(0)
return res

############

class Solution(object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
ans = []

def dfs(path, n, ans):
if len(path) == n:
ans.append(drawChess(path))
return

for i in range(n):
if i not in path and isValidQueen(path, i):
path.append(i)
dfs(path, n, ans)
path.pop()

def isValidQueen(path, k):
for i in range(len(path)):
if abs(k - path[i]) == abs(len(path) - i):
return False
return True

def drawChess(path):
ret = []
chess = [["."] * len(path) for _ in range(len(path))]
for i in range(0, len(path)):
chess[i][path[i]] = "Q"
for chs in chess:
ret.append("".join(chs))
return ret

dfs([], n, ans)
return ans