【综合算法学习】(第十三篇)
目录
解数独(hard)
题目解析
讲解算法原理
编写代码
单词搜索(medium)
题目解析
解析算法原理
编写代码
解数独(hard)
题目解析
1.题目链接:. - 力扣(LeetCode)
2.题目描述
编写⼀个程序,通过填充空格来解决数独问题。
数独的解法需遵循如下规则:
数字1-9在每⼀⾏只能出现⼀次。
数字1-9在每⼀列只能出现⼀次。
数字1-9在每⼀个以粗实线分隔的3x3宫内只能出现⼀次。(请参考⽰例图)
数独部分空格内已填⼊了数字,空⽩格⽤'.'表⽰。
• ⽰例1:
输⼊:board=[["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]
输出:[["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],
["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],
["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],
["3","4","5","2","8","6","1","7","9"]]
解释:输⼊的数独如上图所⽰,唯⼀有效的解决⽅案如下所⽰:
• 提⽰:
board.length==9
board[i].length==9
board[i][j]是⼀位数字或者'.'题⽬数据保证输⼊数独仅有⼀个解
讲解算法原理
解法:算法思路:
为了存储每个位置的元素,我们需要定义⼀个⼆维数组。⾸先,我们记录所有已知的数据,然后遍历所有需要处理的位置,并遍历数字1~9。对于每个位置,我们检查该数字是否可以存放在该位置,同时检查⾏、列和九宫格是否唯⼀。
我们可以使⽤⼀个⼆维数组来记录每个数字在每⼀⾏中是否出现,⼀个⼆维数组来记录每个数字在每⼀列中是否出现。对于九宫格,我们可以以⾏和列除以3得到的商作为九宫格的坐标,并使⽤⼀个三维数组来记录每个数字在每⼀个九宫格中是否出现。在检查是否存在冲突时,只需检查⾏、列和九宫格⾥对应的数字是否已被标记。如果数字⾄少有⼀个位置(⾏、列、九宫格)被标记,则存在冲突,因此不能在该位置放置当前数字。
• 特别地,在本题中,我们需要直接修改给出的数组,因此在找到⼀种可⾏的⽅法时,应该停⽌递
归,以防⽌正确的⽅法被覆盖。
初始化定义:
1. 定义⾏、列、九宫格标记数组以及找到可⾏⽅法的标记变量,将它们初始化为false。
2. 定义⼀个数组来存储每个需要处理的位置。
3. 将题⽬给出的所有元素的⾏、列以及九宫格坐标标记为true。4. 将所有需要处理的位置存⼊数组。
递归函数设计:voiddfs(vector<vector<char>>&board,intpos)参数:pos(当前需要处理的坐标);
返回值:⽆;
函数作⽤:在当前坐标填⼊合适数字,查找数独答案。
递归流程如下:
1. 结束条件:已经处理完所有需要处理的元素。如果找到了可⾏的解决⽅案,则将标记变量更新为true并返回。
2. 获取当前需要处理的元素的⾏列值。
3. 遍历数字1~9。如果当前数字可以填⼊当前位置,并且标记变量未被赋值为true,则将当前位置的⾏、列以及九宫格坐标标记为true,将当前数字赋值给board数组中的相应位置元素,然后对下⼀个位置进⾏递归。
4. 递归结束时,撤回标记。
编写代码
c++算法代码:
class Solution
{bool row[9][10], col[9][10], grid[3][3][10];
public:void solveSudoku(vector<vector<char>>& board) {// 初始化for(int i = 0; i < 9; i++){for(int j = 0; j < 9; j++){if(board[i][j] != '.'){int num = board[i][j] - '0';row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = true;}}}dfs(board);}bool dfs(vector<vector<char>>& board){for(int i = 0; i < 9; i++){for(int j = 0; j < 9; j++){if(board[i][j] == '.'){// 填数for(int num = 1; num <= 9; num++){if(!row[i][num] && !col[j][num] && !grid[i / 3][j / 3]
[num]){board[i][j] = '0' + num;row[i][num] = col[j][num] = grid[i / 3][j / 3]
[num] = true;if(dfs(board) == true) return true; // 重点理解 // 恢复现场board[i][j] = '.';row[i][num] = col[j][num] = grid[i / 3][j / 3]
[num] = false;}}return false; // 重点理解}}}return true; // 重点理解}
};
java算法代码:
class Solution
{boolean[][] row, col;boolean[][][] grid;public void solveSudoku(char[][] board) {row = new boolean[9][10];col = new boolean[9][10];grid = new boolean[3][3][10];// 初始化for(int i = 0; i < 9; i++)for(int j = 0; j < 9; j++)if(board[i][j] != '.'){int num = board[i][j] - '0';row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = true;}dfs(board);}public boolean dfs(char[][] board){for(int i = 0; i < 9; i++){for(int j = 0; j < 9; j++){if(board[i][j] == '.'){// 填数for(int num = 1; num <= 9; num++){// 剪枝if(!row[i][num] && !col[j][num] && !grid[i / 3][j / 3]
[num]){board[i][j] = (char)('0' + num);row[i][num] = col[j][num] = grid[i / 3][j / 3]
[num] = true;if(dfs(board) == true) return true; // 重点理解 // 恢复现场board[i][j] = '.';row[i][num] = col[j][num] = grid[i / 3][j / 3]
[num] = false;}}return false; // 重点理解}}}return true; // 重点理解}
}
单词搜索(medium)
题目解析
1.题目链接:. - 力扣(LeetCode)
2.题目描述
给定⼀个mxn⼆维字符⽹格board和⼀个字符串单词word。如果word存在于⽹格中,返回true;否则,返回false。
单词必须按照字⺟顺序,通过相邻的单元格内的字⺟构成,其中“相邻”单元格是那些⽔平相邻或垂直相邻的单元格。同⼀个单元格内的字⺟不允许被重复使⽤。
• ⽰例1:
输⼊:board=[["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]],word="ABCCED"输出:true
• ⽰例2:
输⼊:board=[["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]],word="SEE"输出:true
• ⽰例3:
输⼊:board=[["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]],word="ABCB"
输出:false
• 提⽰:
m==board.length
n=board[i].length
1<=m,n<=6
1<=word.length<=15
board和word仅由⼤⼩写英⽂字⺟组成
解析算法原理
解法:算法思路:
我们需要假设每个位置的元素作为第⼀个字⺟,然后向相邻的四个⽅向进⾏递归,并且不能出现重复使⽤同⼀个位置的元素。通过深度优先搜索的⽅式,不断地枚举相邻元素作为下⼀个字⺟出现的可能性,并在递归结束时回溯,直到枚举完所有可能性,得到正确的结果。
递归函数设计:booldfs(intx,inty,intstep,vector<vector<char>>&board,stringword,vector<vector<bool>>&vis,int&n,int&m,int&len)
参数:x(当前需要进⾏处理的元素横坐标),y(当前需要进⾏处理的元素横坐标),step(当前已经处理的元素个数),word(当前的字符串状态);
返回值:当前坐标元素作为字符串中下标step的元素出现是否可以找到成⽴的字符串。
函数作⽤:判断当前坐标的元素作为字符串中下标step的元素出现时,向四个⽅向传递,查找是否存在路径结果与字符串相同。
递归函数流程:
1. 遍历每个位置,标记当前位置并将当前位置的字⺟作为⾸字⺟进⾏递归,并且在回溯时撤回标记。
2. 在每个递归的状态中,我们维护⼀个步数step,表⽰当前已经处理了⼏个字⺟。
◦ 若当前位置的字⺟与字符串中的第step个字⺟不相等,则返回false。◦ 若当前step的值与字符串⻓度相等,表⽰存在⼀种路径使得word成⽴,返回true。
3. 对当前位置的上下左右四个相邻位置进⾏递归,若递归结果为true,则返回true。
4. 若相邻的四个位置的递归结果都为false,则返回false。
• 特别地,如果使⽤将当前遍历到的字符赋值为空格,并在回溯时恢复为原来的字⺟的⽅法,则在递归时不会重复遍历当前元素,可达到不使⽤标记数组的⽬的。
编写代码
c++算法代码:
class Solution
{bool vis[7][7];int m, n;
public:bool exist(vector<vector<char>>& board, string word) {m = board.size(), n = board[0].size();for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){if(board[i][j] == word[0]){vis[i][j] = true;if(dfs(board, i, j, word, 1)) return true;vis[i][j] = false;}}return false;}int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};bool dfs(vector<vector<char>>& board, int i, int j, string& word, int pos){if(pos == word.size()) return true;// 向量的⽅式,定义上下左右四个位置for(int k = 0; k < 4; k++){int x = i + dx[k], y = j + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && board[x][y]
== word[pos]){vis[x][y] = true;if(dfs(board, x, y, word, pos + 1)) return true;vis[x][y] = false;}}return false;}
};
java算法代码:
class Solution
{boolean[][] vis;int m, n;char[] word;public boolean exist(char[][] board, String _word) {m = board.length; n = board[0].length;word = _word.toCharArray();vis = new boolean[m][n];for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){if(board[i][j] == word[0]){vis[i][j] = true;if(dfs(board, i, j, 1)) return true;vis[i][j] = false;}}return false;}int[] dx = {0, 0, 1, -1};int[] dy = {1, -1, 0, 0};public boolean dfs(char[][] board, int i, int j, int pos){if(pos == word.length){return true;}// 上下左右去匹配 word[pos]// 利⽤向量数组,⼀个 for 搞定上下左右四个⽅向for(int k = 0; k < 4; k++){int x = i + dx[k], y = j + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && board[x][y]
== word[pos]){vis[x][y] = true;if(dfs(board, x, y, pos + 1)) return true;vis[x][y] = false;}}return false;}
}
相关文章:
【综合算法学习】(第十三篇)
目录 解数独(hard) 题目解析 讲解算法原理 编写代码 单词搜索(medium) 题目解析 解析算法原理 编写代码 解数独(hard) 题目解析 1.题目链接:. - 力扣(LeetCode)…...
Web3 Key Talking #4|Sui有何不同?及其发展路线图
活动时间: 2024 年 10 月 31 日(周四)20:00–21:00(UTC8) 会议链接: 腾讯会议 会议 ID :429–339–777 主持:Sanzhisanzhichazi1 嘉宾:uvdwangtxxl,Sui …...
Axios 请求超时设置无效的问题及解决方案
文章目录 Axios 请求超时设置无效的问题及解决方案1. 引言2. 理解 Axios 的超时机制2.1 Axios 超时的工作原理2.2 超时错误的处理 3. Axios 请求超时设置无效的常见原因3.1 配置错误或遗漏3.2 超时发生在建立连接之前3.3 使用了不支持的传输协议3.4 代理服务器或中间件干扰3.5 …...
数据结构+算法
一、数据结构 1、线性结构 数组: 访问:O(1)访问特定位置的元素;插入:O(n)最坏的情况发生在插入发生在数组的首部并需要移动所有元素时;删除:O(n)最坏的情况发生在删除数组的开头发生并需要移动第一元素后…...
利用ExcelJS封装一个excel表格的导出
ExcelJS 操作和写入Excel 文件。 直接上代码,js部分: exportFn.js import ExcelJS from exceljs; import { saveAs } from file-saver;export function exportExcleUtils(tHeader, filterVal, listData, fileName) {//设置工作簿属性const workbook ne…...
AI 原生时代,更要上云:百度智能云云原生创新实践
本文整理自百度云智峰会 2024 —— 云原生论坛的同名演讲。 我今天分享的主题,是谈谈在云计算和 AI 技术快速发展和深入落地的背景下,百度智能云在云原生的基础设施产品和技术层面做的一些创新实践。 毋庸置疑,过去十几年云计算和 AI 技术是…...
C语言程序编译运行
程序功能:使用 printf() 输出 “Hello, World!”。 C语言源程序: #include <stdio.h> int main() {// printf() 中字符串需要引号printf("Hello, World!");return 0; }编译过程: vim hello.c gcc hello.c -o hello ./hell…...
视频点播系统扩展示例
更多的前端页面(如视频详情页、用户注册页等)。更复杂的业务逻辑(如视频评论、搜索功能等)。安全性和权限管理(如用户角色管理、权限控制等)。其他技术细节(如文件上传、分页查询等)…...
echo $? —— Linux 中的退出状态码详解
在 Linux 系统中,echo $? 是一个非常重要的命令,用于显示上一条命令的退出状态码。这个小小的符号组合可以帮助我们判断命令是否成功执行,同时也为编写自动化脚本提供了基础支持。本文将详细介绍 echo $? 的用法及其在实际开发中的应用。 …...
heic格式转化jpg最简单方法?快来学习这几种简单的转换方法!
heic格式转化jpg最简单方法?在当今的数字图像处理领域,HEIC格式以其卓越的压缩效率和高质量图像表现,正逐渐崭露头角并受到业界的深切关注,HEIC格式凭借先进的压缩技术,成功地在保持图像清晰度的同时,大幅度…...
力扣(leetcode)每日一题 3259 超级饮料的最大强化能量|动态规划
3259. 超级饮料的最大强化能量 题干 来自未来的体育科学家给你两个整数数组 energyDrinkA 和 energyDrinkB,数组长度都等于 n。这两个数组分别代表 A、B 两种不同能量饮料每小时所能提供的强化能量。 你需要每小时饮用一种能量饮料来 最大化 你的总强化能量。然而…...
Webserver(2.7)内存映射
目录 内存映射内存映射相关系统调用内存映射的注意事项如果对mmap的返回值(ptr)做操作,释放内存(munmap)是否能够成功?如果open时O_RDONLY,mmap时prot参数指定PROT_READ | PROT_WRITE会怎样?如果文件偏移量…...
vue3父子组件传值,子组件暴漏方法
1.父传子 defineProps 父组件直接通过属性绑定的方式给子组件绑定数据,子组件通过defineProps接收函数接收 其中v-model是完成事件绑定和事件监听的语法糖。v-model算是v-bind和v-on的简洁写法,等价于 <c-input ref"inputRef" :modelValue…...
Linux_04 Linux常用命令——tar
一、命令格式 tar [选项] [归档文件] [要处理的文件或目录]1、选项 c创建归档文件x解压缩归档文件z使用gzipj使用bzip2v处理过程显示信息f指定归档文件名称 2、归档文件-可指定目录及文件名 /home/wang.tar.gz 3、要处理的文件或目录 /home/study1/wang 二、常见命令 t…...
Java项目实战II基于Java+Spring Boot+MySQL的编程训练系统(源码+数据库+文档)
目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在当今数字…...
Rust:文档注释 //! 和 ///
在 Rust 编程语言中,//! 是一种特殊的文档注释(documentation comment)。它用于为整个模块、结构体、枚举、函数或其他项提供文档说明。与单行注释 // 和多行注释 /* ... */ 不同,//! 和 ///(用于紧跟在项之前的文档注…...
练习LabVIEW第二十七题
学习目标: 刚学了LabVIEW,在网上找了些题,练习一下LabVIEW,有不对不好不足的地方欢迎指正! 第二十七题: 创建一个VI程序模拟温度测量。假设传感器输出电压与温度成正比。例如,当温度为70F时&…...
使用React构建现代Web应用
💖 博客主页:瑕疵的CSDN主页 💻 Gitee主页:瑕疵的gitee主页 🚀 文章专栏:《热点资讯》 使用React构建现代Web应用 1 引言 2 React简介 3 安装React 4 创建React项目 5 设计应用结构 6 创建组件 7 使用组件…...
【系统设计】Merkle 算法在 Git 中的应用:深入理解与实践
引言 在现代软件开发中,Git 已成为版本控制的事实标准。Git 能够快速处理项目的变化,确保代码的完整性,其中一个关键技术就是 Merkle 树。本文将深入探讨 Merkle 算法的原理,以及其在 Git 中的具体应用。 1. Merkle 算法的原理 …...
【umi max】关于umi构建的项目在本地服务运行正常,但是部署时无致命报错却白屏,html文档的#root容器没有子元素的原因及解决办法
我们在部署时运维很可能会因为项目太多,进而放到不同的目录底下,例如project/H5-TEST-DEMO (其中project是项目的存放目录,而H5-TEST-DEMO才是我们部署的项目根目录)于是乎就会出现我们在本地服务里调试得好好的&#…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...




