每日一题——N皇后

菜鸡每日一题系列打卡51

每天一道算法题目 

小伙伴们一起留言打卡

坚持就是胜利,我们一起努力!

题目描述(引自LeetCode)

n皇后问题研究的是如何将n个皇后放置在n × n的棋盘上,并且使皇后彼此之间不能相互攻击。

每日一题——N皇后_第1张图片

上图为8皇后问题的一种解法。给定一个整数n,返回所有不同的n皇后问题的解决方案。每一种解法包含一个明确的n皇后问题的棋子放置方案,该方案中'Q'和'.'分别代表了皇后和空位。

示例:
输入: 4
输出: [
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],


 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。

提示:

皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一到七步,可进可退。(引用自百度百科 - 皇后)

题目分析

N皇后问题又是一个经典的回溯法的应用场景。对于回溯法的题目已经讲的够多的了。三步走,首先创建记录回溯状态的数据结构,然后进行试探,如果试探符合要求就继续向下试探,否则就撤销本次试探。为了方便小伙伴们阅读,菜鸡对代码的结构进行了简单的拆分和注释。话不多说,上代码!

代码实现

class Solution {


    // 结果集
    private List> result = new ArrayList<>();
    // 记录列
    private int[] rows;
    // 记录主对角线
    private int[] rup;
    // 记录副对角线
    private int[] lup;
    // 记录皇后位置
    private int[] queens;


    public List> solveNQueens(int n) {
        rows = new int[n];
        rup = new int[2 * n - 1];
        lup = new int[2 * n - 1];
        queens = new int[n];
        backtrack(n, 0);
        return result;    
    }


    private void backtrack(int n, int row) {
        // 递归终止条件
        if (row >= n) return;


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


            // 符合N皇后的要求
            if (rows[column] + rup[row - column + n - 1] + lup[row + column] == 0) {


                // 试探
                queens[row] = column;
                rows[column] = 1;
                rup[row - column + n - 1] = 1;
                lup[row + column] = 1;


                // 加入结果集
                if (row == n - 1) {
                    List tmp = new ArrayList();
                    for (int i = 0; i < n; i++) {
                        StringBuilder builder = new StringBuilder();
                        for(int j = 0; j < queens[i]; j++) builder.append(".");
                        builder.append("Q");
                        for(int j = 0; j < n - queens[i] - 1; j++) builder.append(".");
                        tmp.add(builder.toString());
                    }
                    result.add(tmp);
                }


                // 回溯
                backtrack(n, row + 1);


                // 撤销
                queens[row] = column;
                rows[column] = 0;
                rup[row - column + n - 1] = 0;
                lup[row + column] = 0;
            }
        }
    }


}

代码分析

对代码进行分析,时间复杂度为O(n!),而就空间而言,采用了额外的数组记录当前的回溯状态,空间复杂度为O(n)。

执行结果

每日一题——N皇后_第2张图片

学习 | 工作 | 分享

????长按关注“有理想的菜鸡

只有你想不到,没有你学不到

你可能感兴趣的:(算法)