class Solution:
def solveNQueens(self, n):
def n_queens_solver(row, visited_cols, unique_y_intercepts, res):
if row == n:
results.append(res)
return
for col in range(n):
if col not in visited_cols and (row + col) not in unique_y_intercepts and (col - row) not in unique_y_intercepts:
visited_cols_dup = visited_cols.copy()
unique_y_intercepts_dup = unique_y_intercepts.copy()
res_dup = res.copy()
visited_cols_dup.add(col)
unique_y_intercepts_dup.add(row + col)
unique_y_intercepts_dup.add(col - row)
this_row = '.' * col + 'Q' + '.' * (n - col - 1)
res_dup.append(this_row)
n_queens_solver(row + 1, visited_cols_dup, unique_y_intercepts_dup, res_dup)
results = []
n_queens_solver(0, set(), set(), [])
return results
我还没有找到解决这个问题的实际方法,我想我的效率很低,但是我不知道我在做什么错。
样本输入:
n = 4
正确的输出:
[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
我的输出:
[]
要考虑唯一的对角线,我想出每个有效的位置都要插入一个女王,我们需要考虑斜率+1
和斜率-1
的所有线。每条线都有一个独特的y轴截距。使用y=x+b
和y=-x+b
,插入皇后的每个潜在点都不必具有(y-x == b
)或(y+x == b
)。
这里我的理由有什么明显的错误之处?
注意-我不是在要求其他或更理想的解决方案。我只是想弄清楚我的思维过程在哪里不正确。
答案 0 :(得分:4)
算法中的错误如下。查看当您尝试将对角线标记为已访问时会发生什么。
让我们画一个4x4板,并为每个单元分配它所在的正斜对角线的数量(将i
+ j
放在行i
和行的正方形上j
):
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
假设您将第一个皇后放在(1,3)
位置。我知道您的算法从第0行开始,但是在这种情况下并不重要。现在,该面板如下所示:
0 1 2 3
1 2 3 Q
2 3 4 5
3 4 5 6
然后将3加到visited_cols
,将3 +1 = 4加到y_intercepts
,并将3-1 = 2加到y_intercepts
。我们有cols = {3}
和y_intercepts = {2,4}
。让我们在板上用X
标记与y_intercept的值2对应的对角线:
0 1 X 3
1 X 3 Q
X 3 4 5
3 4 5 6
现在,假设我们对第二行进行算法,然后尝试将第二个皇后放在正方形(2,0)上。这是有效位置,因为第一任皇后不会攻击该广场。但是您的算法将拒绝该位置,因为row + col = 2 + 0 = 2
位于y_intercepts
集中。发生了什么?我们对正方形(2,0)进行了正斜率测试,但由于y_intercepts
集中有2个而失败了。但是请注意,在检查了负斜对角线(记住3-1 = 2?)之后,在此添加了2。因此,对正斜和负斜对角线的测试混合在一起,导致对平方(2,0)的不正确拒绝。这就是为什么您的程序输出空的results
向量的原因-在算法的某个点上,存在一行,使得其所有平方都被拒绝(类似于我们刚刚观察到的,某些正方形被正确拒绝,而其他正方形被错误地拒绝了) )。
一种解决方法是为正斜对角线和负斜对角线创建两个单独的集合,并检查row + col
是否正斜线和col - row
是否负数。