每日一题——N皇后II

菜鸡每日一题系列打卡52

每天一道算法题目 

小伙伴们一起留言打卡

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

题目描述(引自LeetCode)

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

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

上图为8皇后问题的一种解法。给定一个整数n,返回n皇后不同的解决方案的数量。

示例:
输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],


 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]

提示:

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

题目分析

这道题目和上一道题目如出一辙,唯一不同的是,上一道题目要求输出所有的结果,而这道题目只需要输出结果的数量。相比之下,这道题目的代码就可以写得更简洁了,而且,有上一道题目的基础,解答这道题目的难度大大下降。本文将采用和上一道题目相似的方法进行实现。

实际上,菜鸡在网上看到过利用bitmap解答本题的方法,十分巧妙,在时间复杂度相同的情况下,采用位运算执行效率会更高一些,但相比之下,也显得不够直观,感兴趣的小伙伴可以自行上网查阅。


菜鸡认为,如果是在面试过程中,由于这两种解法的时间复杂度和空间复杂度没有差别,因此,采用本文的解答方式更为稳妥些。但如果是想追求亮点,不妨尝试一下bitmap的解法,不过这多半会让面试官觉得你做过这道题目(哈哈)。

代码实现

class Solution {


    // 结果变量
    private int result;
    // 记录列
    private int[] rows;
    // 记录主对角线
    private int[] rup;
    // 记录副对角线
    private int[] lup;


    public int totalNQueens(int n) {
        rows = new int[n];
        rup = new int[2 * n - 1];
        lup = new int[2 * n - 1];
        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) {
                // 试探
                rows[column] = 1;
                rup[row - column + n - 1] = 1;
                lup[row + column] = 1;
                // 加入结果集
                if (row == n - 1) result++;
                // 回溯
                backtrack(n, row + 1);
                // 撤销
                rows[column] = 0;
                rup[row - column + n - 1] = 0;
                lup[row + column] = 0;
            }
        }
    }
}

代码分析

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

执行结果

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

学习 | 工作 | 分享

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

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

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