
本文详解如何设计正确的递归函数,从指定位置出发沿四个对角线方向逐一检查是否存在其他皇后,避免原实现中重复遍历与误判当前格子的问题,并提供可直接使用的分层递归方案。
本文详解如何设计正确的递归函数,从指定位置出发沿四个对角线方向逐一检查是否存在其他皇后,避免原实现中重复遍历与误判当前格子的问题,并提供可直接使用的分层递归方案。
在解决 N 皇后问题时,判断新放置的皇后是否与已有皇后构成对角线冲突,是关键一步。初学者常尝试用单一递归函数同时探索全部四个对角方向,但容易陷入逻辑陷阱:例如,原始代码 diaCheck(r, c) 在入口处就立即检查 (r, c) 本身——而该位置正是当前待放置皇后的坐标(值为 1),导致函数恒返回 false;更严重的是,它会递归扩散至整个对角线子树(即对每个已访问的空格继续向其四个对角延伸),造成大量冗余检查,甚至误将远处无关皇后判定为冲突。
正确解法应遵循「单向、线性、非回溯」原则:从当前皇后位置出发,沿每条对角线单独、直线式推进,仅检查该方向上的连续格子,直到越界或发现另一皇后。为此,推荐采用双层递归结构:
- 入口方法 diaCheck(int r, int c):不直接检查 (r, c),而是启动四条独立对角线扫描;
- 核心递归方法 diaCheck(int r, int c, int dr, int dc):按固定方向 (dr, dc)(如 (-1,-1) 表示左上)线性递进,每次只移动一步。
以下是完整、健壮的实现:
// 入口方法:启动四条对角线独立检查(跳过当前位置)
public boolean diaCheck(int r, int c) {
return diaCheck(r - 1, c - 1, -1, -1) && // 左上
diaCheck(r - 1, c + 1, -1, +1) && // 右上
diaCheck(r + 1, c - 1, +1, -1) && // 左下
diaCheck(r + 1, c + 1, +1, +1); // 右下
}
// 核心递归方法:沿指定方向 (dr, dc) 线性检查
private boolean diaCheck(int r, int c, int dr, int dc) {
// 边界检查:越界即安全,返回 true
if (r < 0 || r >= board.length || c < 0 || c >= board.length) {
return true;
}
// 冲突检查:若该位置已有皇后,立即返回 false
if (board[r][c] == 1) {
return false;
}
// 递归推进:沿同一方向检查下一格
return diaCheck(r + dr, c + dc, dr, dc);
}关键注意事项:
✅ 入口不查自身:diaCheck(r, c) 从 (r±1, c±1) 开始,规避了当前皇后导致的误判;
✅ 方向参数化:dr/dc 明确控制移动轨迹,确保每条对角线严格线性延伸;
✅ 短路逻辑合理:使用 && 连接四方向结果,任一方向发现冲突即整体返回 false;
✅ 终止条件清晰:越界返回 true(无冲突),遇皇后返回 false(冲突),无歧义。
此设计时间复杂度为 O(n)(单方向最多检查 n 格),空间复杂度为 O(n)(最大递归深度),兼顾正确性、可读性与性能,是 N 皇后对角线校验的标准递归范式。

















