代码随想录-刷题第三十天

332. 重新安排行程

题目链接:332. 重新安排行程

直觉上来看这道题和回溯法没有什么关系,更像是图论中的深度优先搜索。

这道题算是图论里深搜的题目,可以用回溯法的套路来解这道题目,算是拓展一下思路,原来回溯法还可以这么玩!

难度较高,之后再来解决。


51. N皇后

题目链接:51. N皇后

首先来看一下皇后们的约束条件:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线

思路:搜索皇后的位置,可以抽象为一棵树。

下面用一个 3 * 3 的棋盘,将搜索过程抽象为一棵树,如图:

51.N皇后

从图中,可以看出,二维矩阵中矩阵的高就是这棵树的高度,矩阵的宽就是树形结构中每一个节点的宽度。

那么用皇后们的约束条件,回溯搜索这棵树,只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了

class Solution {private List<List<String>> res = new ArrayList<>();public List<List<String>> solveNQueens(int n) {// '.' 表示空,'Q' 表示皇后,初始化空棋盘。char[][] chessboard = new char[n][n];for (char[] c : chessboard) {Arrays.fill(c, '.');}backtracking(n, 0, chessboard);return res;}// n 为输入的棋盘大小// row 是当前递归到棋盘的第几行private void backtracking(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)) {continue;}// 做选择chessboard[row][col] = 'Q';// 进入下一行决策backtracking(n, row + 1, chessboard);// 撤销选择chessboard[row][col] = '.';}}// 二维数组转换为Listprivate List Array2List(char[][] chessboard) {List<String> list = new ArrayList<>();for (char[] c : chessboard) {list.add(String.valueOf(c));}return list;}// 检查是否可以在 chessboard[row][col] 放置皇后private 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;}
}

为什么没有对同一行进行检查呢?

因为在单层搜索的过程中,每一层递归,只会选for循环(也就是同一行)里的一个元素,所以不用去重了。


37. 解数独

题目链接:37. 解数独

一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。

数字 1-9 在每一列只能出现一次。

数字 1-9 在每一个以粗实线分隔的 3 x 3 宫格内只能出现一次。

空白格用 ‘.’ 表示。

解数独

本题中棋盘的每一个位置都要放一个数字(而N皇后是一行只放一个皇后),并检查数字是否合法,解数独的树形结构要比N皇后更宽更深

思路:将问题抽象成树形结构,这个树形结构太大了,抽取一部分,如图所示:

37.解数独

在树形图中可以看出需要的是一个二维的递归(也就是两个for循环嵌套着递归)

一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!

class Solution {public void solveSudoku(char[][] board) {backtracking(board);}private boolean backtracking(char[][] board) {//「一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,// 一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!」for (int i = 0; i < 9; i++) { // 遍历行for (int j = 0; j < 9; j++) { // 遍历列if (board[i][j] != '.') { // 跳过已填入的数字continue;}for (char k = '1'; k <= '9'; k++) {// 判断 board[i][j] 这个位置放 k 是否合适if (isValid(i, j, k, board)) {board[i][j] = k;if (backtracking(board)) {return true; // 如果找到合适一组解立刻返回}board[i][j] = '.';}}// 9个数都试完了,都不行,那么就返回falsereturn false;// 因为如果一行一列确定下来了,这里尝试了9个数都不行,// 说明这个棋盘找不到解决数独问题的解,那么会直接返回。// 这也就是为什么没有终止条件也不会永远填不满棋盘而无限递归下去!}}// 遍历完没有返回false,说明找到了合适棋盘位置了return true;}// 判断 board[i][j] 是否可以填入 valprivate boolean isValid(int row, int col, char val, char[][] board) {// 同行是否重复for (int i = 0; i < 9; i++) {if (board[row][i] == val) {return false;}}// 同列是否重复for (int j = 0; j < 9; j++) {if (board[j][col] == val) {return false;}}// 9宫格里是否重复int startRow = (row / 3) * 3;int startCol = (col / 3) * 3;for (int i = startRow; i < startRow + 3; i++) {for (int j = startCol; j < startCol + 3; j++) {if (board[i][j] == val) {return false;}}}return true;}
}

判断 board[i][j] 是否可以填入 val 的精简写法

boolean isValid(int r, int c, char n, char[][] board) {for (int i = 0; i < 9; i++) {// 判断行是否存在重复if (board[r][i] == n) return false;// 判断列是否存在重复if (board[i][c] == n) return false;// 判断 3 x 3 方框是否存在重复if (board[(r/3)*3 + i/3][(c/3)*3 + i%3] == n)return false;}return true;
}

回溯法总结

回溯法就是一种暴力搜索的方法,重点在于将问题抽象成树形结构,和剪枝。只要出现了递归,就一定会有回溯。

回溯法可以解决以下问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 棋盘问题:N皇后,解数独等等

回溯法主要就是利用递归来搜索问题的解,回溯法的模板如下:

void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果}
}

使用回溯法解决问题不要忘记递归三部曲(1、确定返回值,参数。2、确定终止条件。3、确定单层逻辑。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/283446.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Big Bird]论文解读:Big Bird: Transformers for Longer Sequences

文章目录 1 介绍2 模型架构3 结果 论文&#xff1a;Big Bird: Transformers for Longer Sequences 作者&#xff1a;Manzil Zaheer, Guru Guruganesh, Avinava Dubey, Joshua Ainslie, Chris Alberti, Santiago Ontanon, Philip Pham, Anirudh Ravula, Qifan Wang, Li Yang, Am…

[计网00] 计算机网络开篇导论

目录 前言 计算机网络的概念 计算机网络的分层 计算机网络的分类 网络的标准化工作和相关组织 计算机网络的性能指标 前言 计算机网络在我们的日常生活中无处不在 在网络会有各种各样的协议和封装 保证我们的信息完整,无误的在各个客户端之前传输 计算机网络的概念 四…

c语言 文件与文件操作

&#x1f3e0; 一.引言 我们日常生活中会将我们制作的ppt,word等存放在文件里进行归类&#xff0c;你是否知道我们能用cC语言对文件进行操作呢(比如文件的打开&#xff0c;关闭和读写等)&#xff1f;那接下来跟博主一起来学习下吧。 &#x1f3e0;二.什么是文件 磁盘上的文件就…

TCP/IP详解——FTP 协议,Telnet协议

文章目录 1. FTP 协议1.1 FTP的应用1.2 FTP传输文件的过程1.3 FTP传输模式1.4 主动模式&#xff08;Active Mode&#xff09;1.5 Active Mode 抓包分析1.6 被动模式&#xff08;Passive Mode&#xff09;1.7 Passive Mode 抓包分析 2. Telnet 协议2.1 Telnet 概念2.2 Telnet 协…

Python电能质量扰动信号分类(一)基于LSTM模型的一维信号分类

目录 引言 1 数据集制作与加载 1.1 导入数据 1.2 制作数据集 2 LSTM分类模型和超参数选取 2.1 定义LSTM分类模型 2.2 定义模型参数 3 LSTM模型训练与评估 3.1 模型训练 3.2 模型评估 往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承…

Word写大论文常见问题(持续更新)

脚注横线未定格 解决方案&#xff1a;“视图”-“草图”&#xff0c;“引用”-“显示备注”-选择“脚注分隔符”&#xff0c;把横线前的空格删掉。 2.PPT做的图插入word中清晰度太低 解决方案&#xff1a;PPT-图形-“另存为图片”-“可缩放矢量图格式”-粘贴到word中。

RDD编程

目录 一、RDD编程基础 &#xff08;一&#xff09;RDD创建 &#xff08;二&#xff09;RDD操作 1、转换操作 2、行动操作 3、惰性机制 &#xff08;三&#xff09;持久化 &#xff08;四&#xff09;分区 &#xff08;五&#xff09;一个综合实例 二、键值对RDD &am…

社交网络分析3:社交网络隐私攻击、保护的基本概念和方法 + 去匿名化技术 + 推理攻击技术 + k-匿名 + 基于聚类的隐私保护算法

社交网络分析3&#xff1a;社交网络隐私攻击、保护的基本概念和方法 去匿名化技术 推理攻击技术 k-匿名 基于聚类的隐私保护算法 写在最前面社交网络隐私泄露用户数据暴露的途径复杂行为的隐私风险技术发展带来的隐私挑战经济利益与数据售卖防范措施 社交网络 用户数据隐私…

[AI工具推荐]AiRestful智能API代码生成

智能API代码示例生成工具AiRestful 一、产品介绍二、如何使用1、第一步(必须):2、第二步(可选):3、第三步(智能生成): 三、如何集成到您的网站(应用)1、开始接入2、接入案例 四、注意点 一、产品介绍 AiRestful是一款基于智能AI的,帮助小白快速生成任意编程语言的API接口调用示…

Axure元件的介绍使用以及登录界面

一、Axure元件介绍 简介&#xff1a; Axure元件是一种功能强大的设计工具&#xff0c;专门用于用户体验设计和交互设计。它可以帮助设计师创建可交互的原型&#xff0c;并实现各种界面元素的设计和布局。 Axure元件的基本特点包括&#xff1a; 多样性&#xff1a;Axure元件包括…

【DataSophon】大数据服务组件之Flink升级

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&am…

从 0 开始实现一个 SpringBoot + Vue 项目

从 0 开始实现一个 SpringBoot Vue 项目 从 0 开始实现一个 SpringBoot Vue 项目软件和工具创建 SpringBoot 后端项目创建 MySQL 数据库配置文件实现增删改查接口Model 层mapper 层service 层controller 层测试 从 0 开始实现一个 SpringBoot Vue 项目 软件和工具 后端开发…