LeetCode每日1题--51. N 皇后

78 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第33天,点击查看活动详情

前言

算法的重要性不言而喻!区分度高!

现在学习的门槛低了,只有能上网每个人都可以学编程!培训班6个月就可以培养出来能干活的人,你怎么从这些人中脱颖而出?没错!就是学算法,学一些底层和基础的东西。

说的功利点是为了竞争,卷死对手。真心话说就是能提高自己的基础能力,为技术可持续发展做好充分的准备!!!

提前入门学习书籍:CPrimerPlus、大话数据结构

image-20220705103735001

刷题网站

代码随想录 (programmercarl.com)

leetcode

我是按照代码随想录提供的刷题顺序进行刷题的,大家也可以去刷leetcode最热200道,都可以

刷题嘛,最重要的就是坚持了!!!

画图软件

OneNote

这个要经常用,遇见不懂的流程的话就拿它画一画!

笔记软件

Typoral

题目

leetcode.cn/problems/n-…

image.png

解析

看到困难题不要慌,先去了解下国际象棋的规则!

其实很简单,思路上还是通过回溯去收集,只不过要按照国际象棋的规则进行去重。

国际象棋中的Queen是棋力最强的子,能横着走,斜着走,不能跨着走,而且走的步数是不限的

了解这些规则之后,我们就是先收集各种情况然后再去重

回溯三部曲

  1. 递归参数

参数分别为:

  • n:棋盘的大小
  • row:记录遍历的层级
  • chessboard[][]: 输入结果数组
public void backTrack(int n, int row, char[][] chessboard) {}

  1. 递归终止的条件

终止的条件就是到达叶子结点返回结果

image.png

if (row == n) {

    res.add(Array2List(chessboard));

    return;

}
  1. 单层搜索的逻辑

递归深度由row参数来进行控制,for循环来控制列。

每次都是要从新的一行的起始位置开始搜,所以都是从0开始。

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

    if (isValid (row, col, n, chessboard)) {

        chessboard[row][col] = 'Q';

        backTrack(n, row+1, chessboard);

        chessboard[row][col] = '.';

    }

}
  1. 验证棋盘是否合法

这一步为最关键的一步,怎么验证呢?

  1. 不能同行
  2. 不能同列
  3. 不能同斜线 (45度和135度角) 也就是之前提到按照国际象棋的规则来,Queen之间不能互相影响
public boolean isValid(int row, int col, int n, char[][] chessboard) {

    // 检查列

        for (int i=0; i<row; ++i) { // 相当于剪枝

            if (chessboard[i][col] == 'Q') {

                return false;

            }

        }




        // 检查45度对角线

        for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {

            if (chessboard[i][j] == 'Q') {

                return false;

            }

        }




        // 检查135度对角线

        for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {

            if (chessboard[i][j] == 'Q') {

                return false;

            }

        }

            return true;

        }

完整代码

class Solution {

    List<List<String>> res = new ArrayList<>();


    public List<List<String>> solveNQueens(int n) {

    char[][] chessboard = new char[n][n];

    for (char[] c : chessboard) {

        Arrays.fill(c, '.');

    }

    backTrack(n, 0, chessboard);

        return res;

    }





    public void backTrack(int n, int row, char[][] chessboard) {

        if (row == n) {

            res.add(Array2List(chessboard));

            return;

        }




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

            if (isValid (row, col, n, chessboard)) {

                chessboard[row][col] = 'Q';

                backTrack(n, row+1, chessboard);

                chessboard[row][col] = '.';

            }

        }




    }





    public List Array2List(char[][] chessboard) {

        List<String> list = new ArrayList<>();




        for (char[] c : chessboard) {

            list.add(String.copyValueOf(c));

        }

        return list;

    }





    public boolean isValid(int row, int col, int n, char[][] chessboard) {

    // 检查行列

        for (int i=0; i<row; ++i) { // 相当于剪枝

            if (chessboard[i][col] == 'Q') {

                return false;

            }

        }




        // 检查45度对角线

        for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {

            if (chessboard[i][j] == 'Q') {

                return false;

            }

        }




        // 检查135度对角线

        for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {

            if (chessboard[i][j] == 'Q') {

                return false;

            }

        }

            return true;

        }

}