LeetCode 51困难回溯 · 棋盘
N 皇后 图解题解
这道题到底在问什么
每一行恰好放一个皇后(否则两个皇后必同行互吃)。难点是这一行该放第几列:放下后会顺着竖线和两条斜线封锁一片格子,后面几行只能躲开这些封锁线。求所有摆法,4 皇后共有 2 种。
先想最直接的笨办法
逐行往下放:在当前行从左到右挨个试列,放之前检查这一列、左上斜线、右上斜线上有没有已放的皇后——有冲突就跳过这格试下一列;一整行都没法放,就退回上一行把那儿的皇后挪到下一个可行列(这就是回溯)。(动画第 3 步)
最优解:一步一步想明白
- 3逐行往下放:在当前行从左到右挨个试列,放之前检查这一列、左上斜线、右上斜线上有没有已放的皇后——有冲突就跳过这格试下一列;一整行都没法放,就退回上一行把那儿的皇后挪到下一个可行列(这就是回溯)。
- 44×4 空盘,逐行往下放皇后棋盘全空。我们从最上面的第 0 行开始,在这一行从最左列(列 0)往右挨个尝试,找到一个安全列就落子,然后下到第 1 行重复,直到 4 行都放满就是一个完整方案。
- 5检查 (行0,列0) 安不安全轮到第 0 行。橙色格 (行0,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 6第 0 行皇后放在列 0(行0,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
- 7检查 (行1,列0) 安不安全轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 8撞上第 0 行皇后(同一列)红格说明 (行1,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 9检查 (行1,列1) 安不安全轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 10撞上第 0 行皇后(左上—右下对角线)红格说明 (行1,列1) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 11检查 (行1,列2) 安不安全轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 12第 1 行皇后放在列 2(行1,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
- 13检查 (行2,列0) 安不安全轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 14撞上第 0 行皇后(同一列)红格说明 (行2,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 15检查 (行2,列1) 安不安全轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 16撞上第 1 行皇后(右上—左下对角线)红格说明 (行2,列1) 不安全:它和第 1 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 17检查 (行2,列2) 安不安全轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 18撞上第 0 行皇后(左上—右下对角线)红格说明 (行2,列2) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 19检查 (行2,列3) 安不安全轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 20撞上第 1 行皇后(左上—右下对角线)红格说明 (行2,列3) 不安全:它和第 1 行(列2)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 21第 1 行这一支探完,退回去换位第 1 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
- 22检查 (行1,列3) 安不安全轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 23第 1 行皇后放在列 3(行1,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
- 24检查 (行2,列0) 安不安全轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 25撞上第 0 行皇后(同一列)红格说明 (行2,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 26检查 (行2,列1) 安不安全轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 27第 2 行皇后放在列 1(行2,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
- 28检查 (行3,列0) 安不安全轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 29撞上第 0 行皇后(同一列)红格说明 (行3,列0) 不安全:它和第 0 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 30检查 (行3,列1) 安不安全轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 31撞上第 1 行皇后(右上—左下对角线)红格说明 (行3,列1) 不安全:它和第 1 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 32检查 (行3,列2) 安不安全轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 33撞上第 2 行皇后(左上—右下对角线)红格说明 (行3,列2) 不安全:它和第 2 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 34检查 (行3,列3) 安不安全轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 35撞上第 0 行皇后(左上—右下对角线)红格说明 (行3,列3) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 36第 2 行这一支探完,退回去换位第 2 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
- 37检查 (行2,列2) 安不安全轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 38撞上第 0 行皇后(左上—右下对角线)红格说明 (行2,列2) 不安全:它和第 0 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 39检查 (行2,列3) 安不安全轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 40撞上第 1 行皇后(同一列)红格说明 (行2,列3) 不安全:它和第 1 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 41第 1 行这一支探完,退回去换位第 1 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
- 42第 0 行这一支探完,退回去换位第 0 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
- 43检查 (行0,列1) 安不安全轮到第 0 行。橙色格 (行0,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 44第 0 行皇后放在列 1(行0,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
- 45检查 (行1,列0) 安不安全轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 46撞上第 0 行皇后(右上—左下对角线)红格说明 (行1,列0) 不安全:它和第 0 行(列1)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 47检查 (行1,列1) 安不安全轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 48撞上第 0 行皇后(同一列)红格说明 (行1,列1) 不安全:它和第 0 行(列1)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 49检查 (行1,列2) 安不安全轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 50撞上第 0 行皇后(左上—右下对角线)红格说明 (行1,列2) 不安全:它和第 0 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 51检查 (行1,列3) 安不安全轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 52第 1 行皇后放在列 3(行1,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
- 53检查 (行2,列0) 安不安全轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 54第 2 行皇后放在列 0(行2,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
- 55检查 (行3,列0) 安不安全轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 56撞上第 2 行皇后(同一列)红格说明 (行3,列0) 不安全:它和第 2 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 57检查 (行3,列1) 安不安全轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 58撞上第 0 行皇后(同一列)红格说明 (行3,列1) 不安全:它和第 0 行(列1)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 59检查 (行3,列2) 安不安全轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 60第 3 行皇后放在列 2(行3,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 4 行,继续从列 0 开始试。
- 614 个皇后互不攻击:列序 [1, 3, 0, 2]4 行全部放满且谁也吃不到谁——记下这个方案(每行皇后的列号是 [1, 3, 0, 2])。方案数 +1。然后回溯:撤掉最后放的皇后,回上一行继续试别的列,看还有没有别的摆法。
- 62第 3 行这一支探完,退回去换位第 3 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 3 行继续向右试下一列;本行列都试完就再退回上一行。
- 63检查 (行3,列3) 安不安全轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 64撞上第 1 行皇后(同一列)红格说明 (行3,列3) 不安全:它和第 1 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 65第 2 行这一支探完,退回去换位第 2 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
- 66检查 (行2,列1) 安不安全轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 67撞上第 0 行皇后(同一列)红格说明 (行2,列1) 不安全:它和第 0 行(列1)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 68检查 (行2,列2) 安不安全轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 69撞上第 1 行皇后(右上—左下对角线)红格说明 (行2,列2) 不安全:它和第 1 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 70检查 (行2,列3) 安不安全轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 71撞上第 0 行皇后(左上—右下对角线)红格说明 (行2,列3) 不安全:它和第 0 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 72第 1 行这一支探完,退回去换位第 1 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
- 73第 0 行这一支探完,退回去换位第 0 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
- 74检查 (行0,列2) 安不安全轮到第 0 行。橙色格 (行0,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 75第 0 行皇后放在列 2(行0,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
- 76检查 (行1,列0) 安不安全轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 77第 1 行皇后放在列 0(行1,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
- 78检查 (行2,列0) 安不安全轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 79撞上第 0 行皇后(右上—左下对角线)红格说明 (行2,列0) 不安全:它和第 0 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 80检查 (行2,列1) 安不安全轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 81撞上第 1 行皇后(左上—右下对角线)红格说明 (行2,列1) 不安全:它和第 1 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 82检查 (行2,列2) 安不安全轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 83撞上第 0 行皇后(同一列)红格说明 (行2,列2) 不安全:它和第 0 行(列2)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 84检查 (行2,列3) 安不安全轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 85第 2 行皇后放在列 3(行2,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
- 86检查 (行3,列0) 安不安全轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 87撞上第 1 行皇后(同一列)红格说明 (行3,列0) 不安全:它和第 1 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 88检查 (行3,列1) 安不安全轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 89第 3 行皇后放在列 1(行3,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 4 行,继续从列 0 开始试。
- 904 个皇后互不攻击:列序 [2, 0, 3, 1]4 行全部放满且谁也吃不到谁——记下这个方案(每行皇后的列号是 [2, 0, 3, 1])。方案数 +1。然后回溯:撤掉最后放的皇后,回上一行继续试别的列,看还有没有别的摆法。
- 91第 3 行这一支探完,退回去换位第 3 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 3 行继续向右试下一列;本行列都试完就再退回上一行。
- 92检查 (行3,列2) 安不安全轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 93撞上第 0 行皇后(同一列)红格说明 (行3,列2) 不安全:它和第 0 行(列2)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 94检查 (行3,列3) 安不安全轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 95撞上第 2 行皇后(同一列)红格说明 (行3,列3) 不安全:它和第 2 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 96第 2 行这一支探完,退回去换位第 2 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
- 97第 1 行这一支探完,退回去换位第 1 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
- 98检查 (行1,列1) 安不安全轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 99撞上第 0 行皇后(右上—左下对角线)红格说明 (行1,列1) 不安全:它和第 0 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 100检查 (行1,列2) 安不安全轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 101撞上第 0 行皇后(同一列)红格说明 (行1,列2) 不安全:它和第 0 行(列2)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 102检查 (行1,列3) 安不安全轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 103撞上第 0 行皇后(左上—右下对角线)红格说明 (行1,列3) 不安全:它和第 0 行(列2)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 104第 0 行这一支探完,退回去换位第 0 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
- 105检查 (行0,列3) 安不安全轮到第 0 行。橙色格 (行0,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 106第 0 行皇后放在列 3(行0,列3) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 1 行,继续从列 0 开始试。
- 107检查 (行1,列0) 安不安全轮到第 1 行。橙色格 (行1,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 108第 1 行皇后放在列 0(行1,列0) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
- 109检查 (行2,列0) 安不安全轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 110撞上第 1 行皇后(同一列)红格说明 (行2,列0) 不安全:它和第 1 行(列0)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 111检查 (行2,列1) 安不安全轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 112撞上第 0 行皇后(右上—左下对角线)红格说明 (行2,列1) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 113检查 (行2,列2) 安不安全轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 114第 2 行皇后放在列 2(行2,列2) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 3 行,继续从列 0 开始试。
- 115检查 (行3,列0) 安不安全轮到第 3 行。橙色格 (行3,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 116撞上第 0 行皇后(右上—左下对角线)红格说明 (行3,列0) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 117检查 (行3,列1) 安不安全轮到第 3 行。橙色格 (行3,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 118撞上第 2 行皇后(右上—左下对角线)红格说明 (行3,列1) 不安全:它和第 2 行(列2)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 119检查 (行3,列2) 安不安全轮到第 3 行。橙色格 (行3,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 120撞上第 1 行皇后(左上—右下对角线)红格说明 (行3,列2) 不安全:它和第 1 行(列0)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 121检查 (行3,列3) 安不安全轮到第 3 行。橙色格 (行3,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 122撞上第 0 行皇后(同一列)红格说明 (行3,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 123第 2 行这一支探完,退回去换位第 2 行放在列 2 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 2 行继续向右试下一列;本行列都试完就再退回上一行。
- 124检查 (行2,列3) 安不安全轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 125撞上第 0 行皇后(同一列)红格说明 (行2,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 126第 1 行这一支探完,退回去换位第 1 行放在列 0 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
- 127检查 (行1,列1) 安不安全轮到第 1 行。橙色格 (行1,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 128第 1 行皇后放在列 1(行1,列1) 不在任何危险区,安全!放下皇后,它立刻沿竖线和两条斜线新封锁一批格子(浅橙扩大了)。接着下到第 2 行,继续从列 0 开始试。
- 129检查 (行2,列0) 安不安全轮到第 2 行。橙色格 (行2,列0) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 130撞上第 1 行皇后(右上—左下对角线)红格说明 (行2,列0) 不安全:它和第 1 行(列1)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 131检查 (行2,列1) 安不安全轮到第 2 行。橙色格 (行2,列1) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 132撞上第 0 行皇后(右上—左下对角线)红格说明 (行2,列1) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 133检查 (行2,列2) 安不安全轮到第 2 行。橙色格 (行2,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 134撞上第 1 行皇后(左上—右下对角线)红格说明 (行2,列2) 不安全:它和第 1 行(列1)的皇后处在左上—右下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 135检查 (行2,列3) 安不安全轮到第 2 行。橙色格 (行2,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 136撞上第 0 行皇后(同一列)红格说明 (行2,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 137第 1 行这一支探完,退回去换位第 1 行放在列 1 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 1 行继续向右试下一列;本行列都试完就再退回上一行。
- 138检查 (行1,列2) 安不安全轮到第 1 行。橙色格 (行1,列2) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 139撞上第 0 行皇后(右上—左下对角线)红格说明 (行1,列2) 不安全:它和第 0 行(列3)的皇后处在右上—左下对角线上,会互相攻击。放弃这一列,光标右移去试下一列。
- 140检查 (行1,列3) 安不安全轮到第 1 行。橙色格 (行1,列3) 是这一帧要试的位置。浅橙是上面已放皇后封锁的危险区(同列+两条斜线)。先看看这个橙格落不落在危险区里。
- 141撞上第 0 行皇后(同一列)红格说明 (行1,列3) 不安全:它和第 0 行(列3)的皇后处在同一列上,会互相攻击。放弃这一列,光标右移去试下一列。
- 142第 0 行这一支探完,退回去换位第 0 行放在列 3 的这条分支已经探到底了(要么走出了方案、要么后面无解)。把这个皇后拿走,危险区随之缩小,回到第 0 行继续向右试下一列;本行列都试完就再退回上一行。
- 143最后一个方案:列序 [2, 0, 3, 1]所有行的所有列都试遍、所有分支都回溯完,搜索结束。4×4 棋盘上让 4 个皇后互不攻击,一共只有 2 种摆法。N 越大方案越多,但搜索套路完全一样:逐行放、放前判三向冲突、无路可走就回溯。
完整代码(Python / C++ / Java)
Python
def solveNQueens(n):
res, cols = [], [-1] * n
def valid(row, col):
for r in range(row):
c = cols[r]
if c == col or r - c == row - col \
or r + c == row + col:
return False
return True
def dfs(row):
if row == n:
res.append(cols[:]); return
for col in range(n):
if valid(row, col):
cols[row] = col
dfs(row + 1)
cols[row] = -1
dfs(0)
return resC++
class Solution {
public:
vector<vector<int>> res;
vector<int> cols;
bool valid(int row, int col) {
for (int r = 0; r < row; r++) {
int c = cols[r];
if (c == col || r - c == row - col
|| r + c == row + col) return false;
}
return true;
}
void dfs(int row, int n) {
if (row == n) { res.push_back(cols); return; }
for (int col = 0; col < n; col++) {
if (valid(row, col)) {
cols[row] = col;
dfs(row + 1, n);
cols[row] = -1;
}
}
}
vector<vector<int>> solveNQueens(int n) {
cols.assign(n, -1); dfs(0, n); return res;
}
};Java
class Solution {
List<List<Integer>> res = new ArrayList<>();
int[] cols;
boolean valid(int row, int col) {
for (int r = 0; r < row; r++) {
int c = cols[r];
if (c == col || r - c == row - col
|| r + c == row + col) return false;
}
return true;
}
void dfs(int row, int n) {
if (row == n) {
List<Integer> one = new ArrayList<>();
for (int c : cols) one.add(c);
res.add(one); return;
}
for (int col = 0; col < n; col++) {
if (valid(row, col)) {
cols[row] = col;
dfs(row + 1, n);
cols[row] = -1;
}
}
}
public List<List<Integer>> solveNQueens(int n) {
cols = new int[n];
java.util.Arrays.fill(cols, -1);
dfs(0, n);
return res;
}
}复杂度
时间
O(N!)
最坏要试遍每行每列的组合,时间约 O(N!)(每行可选列因上方皇后封锁而锐减,远小于 N^N)。空间 O(N):一个长度 N 的数组记每行皇后的列号,递归深度也是 N。
空间
O(N)
最坏要试遍每行每列的组合,时间约 O(N!)(每行可选列因上方皇后封锁而锐减,远小于 N^N)。空间 O(N):一个长度 N 的数组记每行皇后的列号,递归深度也是 N。
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 N 皇后 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
怎么把 O(N) 的 valid 检查降到 O(1)?+
用三个布尔/集合分别记「占用的列、占用的主对角线 row-col、占用的副对角线 row+col」,放子时打标、撤子时清标,判冲突直接查表。
只要方案个数(LC 52)怎么办?+
同一套回溯,把收集结果改成计数器 +1 即可。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄把 N 皇后 一步步讲透(全站已上线 905 份讲透,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
把这道题真正拿下
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。