当前位置: 首页 > article >正文

[Lc4_dfs] 解数独 | 单词搜索

目录

1.解数独

题解

2.单词搜索

题解


1.解数独

链接:37. 解数独

编写一个程序,通过填充空格来解决数独问题。

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

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 '.' 表示。


题解

  • 上面的是判断是否是有效数独,这里是填数独。
  • 这里还是用上面的三个bool类型数组,来判断这个数能不能放。
  • 这里我们一格一格的放,每个格子可以放1-9中其中一个数,但是肯定会是存在 剪枝 情况的。

具体能不能放还是借助那三个bool类型数组来判断。

  • 我们递归就是拿着这个棋盘,开始依次遍历,看那个是空的就开始填,填的时候判断一下能填在填不能填就不填。
  • 然后能填递归到下一层,但是有可能这个能填的分支下面递归有的位置1 ~ 9都不能填的情况。
  • 因此这个分支可能是得不到正确结果的,那上面怎么知道你这种情况不行的呢?
  • 因此这个 递归函数 要有一个bool类型的返回值,当遇到某个格子1 ~ 9都不能填直接向上返回一个false,告诉它这个位置你填1不行,你要把这个位置填上2然后在往下试。

递归函数 参数只要把这个board给我就行了。bool dfs(board)。

class Solution {
public:bool checkrow[9][10]={}, checkcol[9][10]={}, grip[3][3][10]={};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';checkrow[i][num] = checkcol[j][num] = grip[i/3][j/3][num] = true;}}}dfs(board,0,0);}bool dfs(vector<vector<char>>& board, int row, int col) {if(row == 9) return true;  // 修正终止条件if(col == 9) return dfs(board, row+1, 0);if(board[row][col] != '.') {  // 修正非空推进return dfs(board, row, col+1);}for(int i=1; i<=9; i++) {  // 修正数字范围if(!checkrow[row][i] && !checkcol[col][i] && !grip[row/3][col/3][i]) {// 标记数字board[row][col] = i+'0';checkrow[row][i] = checkcol[col][i] = grip[row/3][col/3][i] = true;if(dfs(board, row, col+1)) return true; //!!!!!成功路径要正确终止,来满足递归的返回// 回溯恢复board[row][col] = '.';checkrow[row][i] = checkcol[col][i] = grip[row/3][col/3][i] = false;}}return false;}
};

//!!!!!成功路径要正确终止,来满足递归的返回

if(dfs(board, row, col+1))  return true; 

优化版本:

class Solution {
public:bool checkrow[9][10] = {false};  // 记录行数字存在情况bool checkcol[9][10] = {false};  // 记录列数字存在情况bool grip[3][3][10] = {false};   // 记录九宫格数字存在情况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';mark(i, j, num, true);}}}dfs(board, 0, 0);}bool dfs(vector<vector<char>>& board, int row, int col) {if(row == 9) return true;    // 正确终止条件if(col == 9) return dfs(board, row+1, 0);// 跳过已填数字if(board[row][col] != '.') {return dfs(board, row, col+1);}for(int num = 1; num <= 9; num++) {  // 修正数字范围if(isValid(row, col, num)) {board[row][col] = num + '0';mark(row, col, num, true);if(dfs(board, row, col+1)) return true;// 回溯恢复mark(row, col, num, false);board[row][col] = '.';}}return false;}private:bool isValid(int row, int col, int num) {return !checkrow[row][num] && !checkcol[col][num] &&!grip[row/3][col/3][num];}void mark(int row, int col, int num, bool flag) {checkrow[row][num] = flag;checkcol[col][num] = flag;grip[row/3][col/3][num] = flag;}
};

2.单词搜索

链接:79. 单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:


题解

给一个mxn board二维数组,让在数组中找是否存在字符串单词 word

注意只能上下左右去找,不能斜着找。

我们在这个矩阵中依次找到word里面的所有字符。

  • 首先在这个矩阵里面 先一行一行的扫描 找到word里面第一个字符
  • 当找到第一个字符时,就从这个字符开始去匹配其他剩余的字符,注意只能上下左右去匹配
  • 如果上下左右都不匹配说明这个位置是一次失败的匹配。
  • 那就在去找其他位置能匹配的第一个字符。
  • 如果找到还是 上下左右去匹配,如果能匹配成功说明这个矩阵有这个单词。

如果把这道题抽象一下,你会发现刚刚的过程就是 解决迷宫常用的方式,深度优先遍历。

如果走不通就回溯一下,再往下走,直到找到一个正确结果为止。

接下来我们考虑 递归函数 如何设计

  • 从某个节点开始上下左右匹配下一个字符,所以则函数体干的就是给一个位置然后 上下左右去匹配下一个字符。
  • 这个参数首先把这个board给我,然后第一个字符的位置,然后给我要匹配字符串中下一个字符的位置。
  • dfs(board,i,j,s,pos),注意看这个决策树我们从一个位置走可能走失败,上面调用dfs的得知道是找成功还是失败,所以dfs有一个bool类型的返回值
  • bool dfs(board,i,j,s,pos) 失败就去另一条路径。

剪枝就是那一个位置能匹配就去走那一个位置。

回溯 一条路径找失败往上走就是回溯,往下走之前你弄了什么,反着来就可以了。


下面是细节问题:二维矩阵搜索中,经常要注意的细节

不能走重复的路

就比如下面的这个位置,一直会是重复的。之前用过的下一次不能在找了。

这里我们有两种方法规避。

1. 用一个bool类型的跟原始数组大小一样的二维数组 bool visit[][]。

  • 用这个数组来标记当前这个位置是否被使用过。
  • 使用过就把这个位置标记成true。
  • 然后到下一层的时候就考虑一下上一个位置是否是ture,是就不走,不是就可以走。

2. 修改原始矩阵的值。

  • 比如说把被使用的位置的值修改成*,面试时还是要问一下能否修改,能修改再用这种方法。
  • 但是还有一个问题你修改完去往下一层,然后再回来的时候你要把被修改的值在还原回来。

这里在写代码去上下左右匹配的时候有两种写法:

  • 可以分别写上下左右四个函数去匹配。
  • 我们可以用向量的方式,定义上下左右四个位置。
  • 然后仅需一次for循环就可以把上下左右都考虑进去了。

单独看这个i,上下左右就是在原始的i基础上要么不变,要么+1,要么-1

所以可以搞一个数组 int dx[4]={0,0,1,-1}; 这个表示i接下来可能的偏移量。

同理j也有四个偏移量 int dy[4]={-1,1,0,0}; 然后这两个就可以上下凑一起使用。

class Solution {
public:int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};int m,n;vector<vector<bool>> check;bool exist(vector<vector<char>>& board, string word) {m=board.size();n=board[0].size();check.resize(m,vector<bool>(n,false));// 遍历所有起点for(int i = 0; i < m; ++i) {for(int j = 0; j < n; ++j) {if(board[i][j] == word[0]){check[i][j]=true;if(dfs(board,i,j,word,1)) return true;check[i][j]=false;//以这个点开始搜索,搜索完之后发现不行 //回溯}}}return false;}bool dfs(vector<vector<char>>& board,int i,int j, string s,int pos)
{if(pos == s.size()) return true;for(int k=0;k<4;k++)  //来实现上下左右的移动{int x=i+dx[k],y=j+dy[k];
//这里的检查和bfs 是一样的if(x >= 0 && x < m && y >= 0 && y < n && check[x][y] == false && board[x][y] == s[pos]){if(board[x][y]==s[pos]){check[x][y]=true;if(dfs(board,x,y,s,pos+1)) return true;check[x][y]=false;}}}return false;
} 
};

相关文章:

[Lc4_dfs] 解数独 | 单词搜索

目录 1.解数独 题解 2.单词搜索 题解 1.解数独 链接&#xff1a;37. 解数独 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线…...

day17 学习笔记

文章目录 前言一、数组的增删改查1.resize函数2.append函数3.insert函数4.delete函数5.argwhere函数6.unique函数 二、统计函数1.amax&#xff0c;amin函数2.ptp函数3.median函数4.mean函数5.average函数6.var&#xff0c;std函数 前言 通过今天的学习&#xff0c;我掌握了num…...

自动语音识别(ASR)技术详解

语音识别&#xff08;Automatic Speech Recognition, ASR&#xff09;是人工智能和自然语言处理领域的重要技术&#xff0c;旨在将人类的语音信号转换为对应的文本。近年来&#xff0c;深度学习的突破推动语音识别系统从实验室走入日常生活&#xff0c;为智能助手、实时翻译、医…...

git | 版本切换的相关指令

常见指令 git log --oneline #查看历史提交 git tag latest-backup # 对当前的提交进行标记&#xff0c;标记名为latest-backup git checkout -b old-version 55b16aa # 切换到[55b16aa]的提交中&#xff0c;并标记为[old-version]的分支 git checkout master …...

19.OpenCV图像二值化

OpenCV图像二值化 图像二值化&#xff08;Binarization&#xff09;是图像预处理中的一种常用技术&#xff0c;其目的是将图像中的像素值分为两个类别——通常是“前景”和“背景”或者说0和255。二值化能够简化图像信息&#xff0c;为后续的形态学处理、边缘检测、目标识别等…...

通过Appium理解MCP架构

MCP即Model Context Protocol&#xff08;模型上下文协议&#xff09;&#xff0c;是由Anthropic公司于2024年11月26日推出的开放标准框架&#xff0c;旨在为大型语言模型与外部数据源、工具及系统建立标准化交互协议&#xff0c;以打破AI与数据之间的连接壁垒。 MCP架构与Appi…...

分享一个Pyside6实现web数据展示界面的效果图

今天又是有问题直接找DS的一天&#xff0c;每日一问&#xff0c;今天我的问题是“怎么将pyside6生成的界面转成web界面&#xff0c;使用python语言实现web界面”&#xff0c;等了一会&#xff0c;DS给我提供了两种方案&#xff0c;方案如下&#xff1a; 然后&#xff0c;让我们…...

FALL靶场通关攻略

1&#xff0c;下载好靶机后打开&#xff0c;通过kali扫描靶机ip和端口&#xff0c;得到靶机ip为192.168.50.144 2&#xff0c;扫描目录 3&#xff0c;访问靶机 4&#xff0c;访问扫描到的test.php,得到缺少GET请求参数的提示 5&#xff0c;使用FUZZ来扫出参数为file 6&#xff…...

Mybatis日志模块分析--适配器模式+代理模式

适配器模式 日志在我们开发过程中占据了一个非常重要的地位&#xff0c;是开发和运维管理之间的桥梁&#xff0c;在Java中的日志框架也非常多&#xff0c;Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等&#xff0c;这些工具对外的接口也都不尽相同&#xff0c;为…...

HTTP介绍以及(GET/POST/PUT/DELETE)应用介绍

WWW 是 “World Wide Web” 的缩写&#xff0c;中文名为 “万维网”。它是一个基于超文本和 HTTP 协议的全球性信息系统&#xff0c;通过互联网连接了世界各地的服务器和用户。用户可以使用浏览器访问各种网站&#xff0c;浏览网页、获取信息、进行交互等。 WWW 的核心技术包…...

圆球法线图,图生法线图 图片生成法线图

目录 圆球法线图 根据图片生成法线图 深度图计算法线图 圆球法线图 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D# 定义球体的参数 radius 1.0 resolution 100# 生成球体表面的点 u np.linspace(0, 2 * np.pi, resoluti…...

notepad++ 正则表达式

注意&#xff1a;Notepad正则表达式字符串最长不能超过69个字符 \ 转义字符 如&#xff1a;要使用 “\” 本身, 则应该使用“\\” \t Tab制表符 注&#xff1a;扩展和正则表达式都支持 \r 回车符CR 注&#xff1a;扩展支持&#xff0c;正则表达式不支持 \n 换行符…...

Java基于SpringBoot的网络云端日记本系统,附源码+文档说明

博主介绍&#xff1a;✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…...

【自用记录】本地关联GitHub以及遇到的问题

最近终于又想起GitHub&#xff0c;想上传代码和项目到仓库里。 由于很早之前有在本地连接过GitHub&#xff08;但没怎么用&#xff09;&#xff0c;现在需要重新搞起&#xff08;操作忘得差不多&#xff09;。 在看教程实操的过程中遇到了一些小问题&#xff0c;遂记录一下。 前…...

页码设置相关问题记录

Q&#xff1a;中间没有显示页码怎么办&#xff1f; A&#xff1a;“页眉和页脚”-“页码”-“页面底端”-“普通数字2” Q&#xff1a;想让页码在某几节连续怎么办&#xff1f; A&#xff1a; ① 先保证节与节之间插入了“分节符”&#xff08;如何插入分节符和如何显示分节符…...

什么是数据集市

数据集市&#xff08;Data Mart&#xff09;是数据管理领域的核心概念&#xff0c;其定义为面向特定业务领域或用户群体的小型数据仓库子集&#xff0c;专注于部门级业务分析&#xff0c;具有快速响应、灵活部署等特点。以下从定义、特点、类型、结构、应用场景及与其他数据架构…...

Python 的未来:在多元变革中持续领跑

一、从工具到生态&#xff1a;Python 的核心优势筑牢发展根基 Python 自诞生以来&#xff0c;始终以 “简洁易用” 和 “跨界融合” 为标签&#xff0c;在技术快速迭代的时代展现出惊人的韧性。其核心竞争力不仅在于语法的直观性 —— 让开发者专注于逻辑实现而非语法细节&…...

【HC-05蓝牙模块】主要性能指标与通信基础知识

一、HC-05 基础学习视频 HC-05蓝牙串口通信模块调试与应用1 二、HC-05学习视频课件...

深度学习中的数据类型

1. NumPy 数组 (numpy.ndarray) 核心定位&#xff1a;科学计算的基础工具&#xff0c;处理数值多维数组。 特点&#xff1a; 高效数值运算&#xff1a;底层用 C 实现&#xff0c;适合数学计算&#xff08;如矩阵乘法、傅里叶变换&#xff09;。 内存连续存储&#xff1a;数据…...

如何缩短研发周期,降低研发成本?全星APQP软件为您提供解决方案

如何缩短研发周期&#xff0c;降低研发成本&#xff1f;全星APQP软件为您提供解决方案 一、 系统概述 全星研发管理APQP软件系统是一款专为产品研发和质量管控打造的智能化平台&#xff0c;旨在帮助企业高效推进APQP&#xff08;先期产品质量策划&#xff09;流程&#xff0c…...

嵌入式系统安全架构白皮书

嵌入式系统安全架构白皮书 一、安全威胁模型 1.1 典型攻击面分析 #mermaid-svg-mxWZ8IOtOmMv6YLV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mxWZ8IOtOmMv6YLV .error-icon{fill:#552222;}#mermaid-svg-mxWZ8I…...

MQTT之重复消息(5、TCP重连和MQTT重连)

目录 1. TCP 协议层的重传&#xff08;原生机制&#xff09; 2. 触发 TCP 重传的具体场景 3、TCP 重传的关键参数&#xff08;了解&#xff09; 第一、重传超时(RTO - Retransmission Timeout) 第二、重传次数 第三、累计时间 vs 本次 RTO 的区别 第四.常见问题解答 第…...

Github Webhook 以及主动式

Github配置 GitHub 默认支持两种 Content-Type: application/json application/x-www-form-urlencoded 特别要注意 Content-Type 我们选择: application/json Flask代码 import os import shutil import subprocess from flask import Flask, request, jsonifyapp = Fla…...

猜猜我用的是哪个大模型?我的世界游戏界面简单的模拟效果

我的罗里吧嗦的&#xff0c;根据小朋友的要求&#xff0c;边听边写边输入的提示词&#xff1a; 请生成一段完整的在网页中用html5和javascript代码模拟“我的世界”中游戏场景的互动画面&#xff0c;要求提供若干人物选项可以选择&#xff0c;请自行选择需要使用哪些库或框架来…...

基于龙芯3A5000处理器,全国产标准6U VPX板卡解决方案

1&#xff0c;产品功能 本产品为一款高可靠性的基于龙芯3A5000处理器以及 7A2000芯片组的标准6U VPX板卡&#xff0c;具有以太网、SATA、PCIE&#xff0c;以及显示等接口&#xff0c;产品功能框图如图1所示&#xff1a; 图1 系统框图 2&#xff0c;技术指标 序号 项目 指标…...

Unity编辑器功能及拓展(3) —[Attribute]特性

在 Unity 中&#xff0c;[Attribute]格式的特性是用于扩展编辑器功能、控制序列化行为和调整 Inspector 显示,进行编辑器拓展的核心工具。 一.基础编辑器拓展 1.基础序列化控制 1.[SerializeField] 强制显示私有变量到Inspector 2.[HideInInspector] 隐藏该字段在Inspect…...

每日一题之既约分数

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 如果一个分数的分子和分母的最大公约数是 1&#xff0c;这个分数称为既约分数。 例如 3/4,1/8,7/1​&#xff0c; 都是既约分数。 请问&#xff0c;有多少个既约分…...

C++作用域辨识详解

在 C 中&#xff0c;作用域&#xff08;Scope&#xff09;定义了变量、函数、类等标识符的可见性和生命周期。理解作用域对于编写清晰、高效的代码至关重要。以下是 C 中作用域的详细分类和说明。 1. 全局作用域&#xff08;Global Scope&#xff09; 全局作用域是指在所有函…...

wait的概念和使用方法

在C语言中&#xff0c;wait 函数主要用于进程管理&#xff0c;它是一个系统调用&#xff0c;定义在 <sys/wait.h> 头文件中&#xff0c;用于让父进程等待其子进程结束&#xff0c;并获取子进程的终止状态。下面为你详细介绍其概念和使用方法。 概念 wait 函数的原型如下…...

HarmonyOS NEXT——鸿蒙神策埋点(二)

在上一章我分享了鸿蒙客户端集成神策埋点sdk的过程&#xff0c;现在我们需要服务端的小伙伴配置集成服务端sdk接收处理数据信息&#xff0c;以下是集成的过程。 Java服务端sdk集成 1、获取神策数据平台url地址 1、导入集成&#xff1a; dependencies {compile com.sensorsda…...