🧮 Algorithm Notebook
1、算法准备
1.1 牛客网编程OJ的典型输入输出
2、算法框架
2.1 动态规划
2.1.1 斐波那契数列
2.1.2 背包问题
2.1.3 贪心算法
2.1.4 序列和数组类问题
2.1.5 编辑距离
2.1.6 高楼扔鸡蛋
2.1.7 股票问题系列通解
2.1.8 最长有效括号
2.1.9 剪绳子
2.1.10 正则表达式匹配
2.2 二分查找
2.2.1 二分查找框架
2.2.2 搜索旋转排序数组
2.3 链表
2.3.1 反转链表
2.3.2 相交链表
2.3.3 合并链表
2.3.4 链表中倒数第k个节点
2.3.5 复制带随机指针的链表
2.4 排序算法
2.4.1 常见排序算法
2.5 二叉树
2.5.1 二叉树遍历
2.5.2 岛屿问题
2.5.3 二叉树路径问题
2.5.4 构造二叉树
2.6 回溯算法
2.6.1 回溯算法解题框架
2.6.2 N皇后
2.7 数组
2.7.1 删除有序数组中的重复项
2.7.2 滑动窗口最大值
2.7.3 调整数组顺序使奇数位于偶数前面
2.7.4 螺旋矩阵
2.7.5 多数元素
2.7.6 最大数
2.7.7 和为s的两个数字
2.7.8 构建乘积数组
2.7.9 两数之和
2.8 字符串
2.8.1 最小覆盖子串
2.8.2 比较版本号
2.8.3 验证IP地址
2.8.4 基本计算器 II
2.8.5 字符串解码
2.8.6 移掉 K 位数字
2.8.7 无重复字符的最长子串
2.8.8 第一个只出现一次的字符
2.8.9 翻转字符串里的单词
2.8.10 字符串转换整数 (atoi)
2.8.11 字符串四则运算
2.9 栈
2.9.1 最小栈
2.9.2 弹出序列
2.10 数学
2.10.1 用 Rand7() 实现 Rand10()
2.10.2 只出现一次的数字
2.10.3 整数反转
2.10.4 求1+2+…+n
2.10.5 二进制中1的个数
2.10.6 幂运算
2.10.7 1~n 整数中 1 出现的次数
2.10.8 数字序列中某一位的数字
2.10.9 丑数
2.10.10 n个骰子的点数
2.10.11 圆圈中最后剩下的数字
2.10.12 不用加减乘除做加法
2.10.13 x 的平方根
2.11 设计
2.11.1 LRU 缓存机制
-
+
游客
注册
登录
N皇后
## 1 题目 n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。 **示例 1:** ![](/media/202106/2021-06-27_194424.png) ```txt 输入:n = 4 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] 解释:如上图所示,4 皇后问题存在两个不同的解法。 ``` **示例 2:** ```txt 输入:n = 1 输出:[["Q"]] ``` **提示:** * 1 <= n <= 9 * 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。 ## 2 解题思路 ### 2.1 回溯算法 #### 2.1.1 问题分析 1. N 皇后的问题本质上跟[全排列](https://notebook.ricear.com/project-21/doc-738)问题差不多,决策树的每一层表示棋盘的每一行,每个节点可以做出的选择是在该行的任意一列放置一个皇后。 2. 函数 `backtrack` 依然像个在决策树上游走的指针,通过 `row` 和 `col` 就可以表示函数遍历到的位置,通过 `isValid` 函数可以将不符合条件的情况进行剪枝。![](/media/202106/2021-06-27_195120.png) #### 2.1.2 参考代码 ```java /** * 将字符数组转化为字符串 * @param array 字符数组 * @return 字符数组对应的字符串 */ public static String charArrayToString(char[] array) { return Arrays.toString(array).replaceAll("[\\[\\]\\s,]", ""); } /** * 判断是否可以在 track[row][col] 放置皇后 * * @param track 路径 * @param row 行 * @param col 列 * @return 是否可以在 track[row][col] 放置皇后 */ private boolean isValid(ArrayList<String> track, int row, int col) { int rowLen = track.size(); char[] rowArr = track.get(row).toCharArray(); // 检查所在行是否有冲突 for (int i = 0; i < rowArr.length; i++) { if (i != col && rowArr[i] == 'Q') { return false; } } // 检查所在列是否有冲突 for (int i = 0; i < rowLen; i++) { if (i != row && track.get(i).charAt(col) == 'Q') { return false; } } // 判断左上角所对应的斜线上是否有冲突 // 左上 int rowTemp = row, colTemp = col; while (rowTemp >= 0 && colTemp >= 0) { if (rowTemp != row && colTemp != col && track.get(rowTemp).charAt(colTemp) == 'Q') { return false; } rowTemp--; colTemp--; } // 右下 rowTemp = row; colTemp = col; while (rowTemp < rowLen && colTemp < rowLen) { if (rowTemp != row && colTemp != col && track.get(rowTemp).charAt(colTemp) == 'Q') { return false; } rowTemp++; colTemp++; } // 判断右上角所对应的斜线上是否有冲突 // 右上 rowTemp = row; colTemp = col; while (rowTemp >= 0 && colTemp < rowLen) { if (rowTemp != row && colTemp != col && track.get(rowTemp).charAt(colTemp) == 'Q') { return false; } rowTemp--; colTemp++; } // 左下 rowTemp = row; colTemp = col; while (rowTemp < rowLen && colTemp >= 0) { if (rowTemp != row && colTemp != col && track.get(rowTemp).charAt(colTemp) == 'Q') { return false; } rowTemp++; colTemp--; } return true; } /** * 回溯算法 * 【路径】:track 中小于 row 的那些行都已经成功放置了皇后 * 【选择列表】:第 row 行的所有列都是放置皇后的选择 * 【结束条件】:row 超过 track 的最后一行 * @param row * @param track * @param res */ public void backtrack(int row, ArrayList<String> track, List<List<String>> res) { // 触发结束条件 if (row == track.size()) { ArrayList<String> trackTemp = new ArrayList<>(); trackTemp.addAll(track); res.add(trackTemp); return; } int rowLen = track.get(row).length(); for (int col = 0; col < rowLen; col++) { // 排除不合法选择 if (!isValid(track, row, col)) { continue; } // 做选择 char[] array = track.get(row).toCharArray(); array[col] = 'Q'; track.set(row, charArrayToString(array)); // 进入下一行决策 backtrack(row + 1, track, res); // 撤销选择 array[col] = '.'; track.set(row, charArrayToString(array)); } } /** * 51. N 皇后 * * @param n 皇后个数 * @return 所有不同的 n 皇后问题 的棋子放置方案 */ public List<List<String>> solveNQueens(int n) { List<List<String>> res = new ArrayList<>(); // 初始化棋盘,“.”表示空,“Q”表示皇后 ArrayList<String> track = new ArrayList<>(); for (int i = 0; i < n; i++) { track.add(String.join("", Collections.nCopies(n, "."))); } backtrack(0, track, res); return res; } ``` ## 参考文献 1. [51. N 皇后](https://leetcode-cn.com/problems/n-queens)。 2. [回溯算法解题套路框架](https://labuladong.gitbook.io/algo/mu-lu-ye-3/mu-lu-ye/hui-su-suan-fa-xiang-jie-xiu-ding-ban)。
ricear
2021年8月22日 20:55
©
BY-NC-ND(4.0)
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码