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

LeetCode 面试经典 150_矩阵_有效的数独(34_36_C++_中等)(额外数组)

LeetCode 面试经典 150_矩阵_有效的数独(34_36_C++_中等)

    • 题目描述:
    • 输入输出样例:
    • 题解:
      • 解题思路:
        • 思路一(暴力破解):
        • 思路二(额外数组:遍历一遍数组):
      • 代码实现
        • 代码实现(思路一(暴力破解)):
        • 代码实现(思路二(额外数组:遍历一遍数组)):
        • 以思路二为例进行调试

题目描述:

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 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”]]

输出:true
解释

示例 2:
输入:board =
[[“8”,“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”]]
输出:false
解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。

提示:
board.length== 9
board[i].length == 9
board[i][j] 是一位数字(1-9)或者 ‘.’9

题解:

解题思路:

思路一(暴力破解):

1、具体思路如下

  • 判断每一行,数字 1-9 在每一行只能出现一次。
  • 判断每一列,数字 1-9 在每一列只能出现一次。
  • 判断每一 3x3 宫内,数字 1-9 只能出现一次。

使用哈希集合来判断每个数字出现的次数,出现过的数字会存储在哈希集合中,若再次出现则返回 false

2、复杂度分析:
① 时间复杂度:O(1)。数独共有 81 个单元格,只需要对每个单元格遍历一次即可。
② 空间复杂度:O(1)。由于数独的大小固定,因此哈希表的空间也是固定的。

思路二(额外数组:遍历一遍数组):

1、使用数组代替哈希表,使用三个数组来存储三类的判断。

  • rows[9][9] rows[i][index] 代表第 i 行,数字 index+1 出现的次数。
  • cols[9][9] cols[j][index] 代表第 j 列,数字 index+1 出现的次数。
  • subboxs[3][3][9] subboxs[i/3][j/3][index] 代表第 (i/3, j/3) 子宫格中数字 index+1 出现的次数。

2、复杂度分析
① 时间复杂度:O(1)。数独共有 81 个单元格,只需要对每个单元格遍历一次即可。
② 空间复杂度:O(1)。由于数独的大小固定,因此哈希表的空间也是固定的。

代码实现

代码实现(思路一(暴力破解)):
class Solution1 {
public:bool isValidSudoku(vector<vector<char>>& board) {int rowSize = board.size();  // 获取数独棋盘的行数int colSize = board[0].size();  // 获取数独棋盘的列数unordered_set<char> set;  // 用于存储当前行、列和 3x3 宫的已见数字,确保数字不重复// 判断每一行,数字 1-9 在每一行只能出现一次for (int i = 0; i < rowSize; i++) {  // 遍历每一行set.clear();  // 清空 set,用于存储当前行已经出现的数字for (int j = 0; j < colSize; j++) {  // 遍历当前行的每一列if (board[i][j] != '.') {  // 如果该位置是一个数字(不是 '.')if (set.count(board[i][j])) {  // 如果数字已经出现过return false;  // 数字重复,返回 false}set.insert(board[i][j]);  // 否则,加入 set,标记这个数字已经出现过}}}// 判断每一列,数字 1-9 在每一列只能出现一次for (int j = 0; j < colSize; j++) {  // 遍历每一列set.clear();  // 清空 set,用于存储当前列已经出现的数字for (int i = 0; i < rowSize; i++) {  // 遍历当前列的每一行if (board[i][j] != '.') {  // 如果该位置是一个数字(不是 '.')if (set.count(board[i][j])) {  // 如果数字已经出现过return false;  // 数字重复,返回 false}set.insert(board[i][j]);  // 否则,加入 set,标记这个数字已经出现过}}}// 判断每一个 3x3 宫内,数字 1-9 只能出现一次for (int i = 0; i < rowSize; i += 3) {  // 遍历每一个 3x3 宫的起始行for (int j = 0; j < colSize; j += 3) {  // 遍历每一个 3x3 宫的起始列set.clear();  // 清空 set,用于存储当前 3x3 宫内已经出现的数字for (int row = 0; row < 3; row++) {  // 遍历 3x3 宫内的行for (int col = 0; col < 3; col++) {  // 遍历 3x3 宮内的列char c = board[i + row][j + col];  // 获取当前 3x3 宮内的数字if (c != '.') {  // 如果当前位置有数字if (set.count(c)) {  // 如果该数字已经出现过return false;  // 数字重复,返回 false}set.insert(c);  // 否则,加入 set,标记这个数字已经出现过}}}}}return true;  // 如果没有重复数字,返回 true,表示数独有效}
};
代码实现(思路二(额外数组:遍历一遍数组)):
class Solution2 {
public:bool isValidSudoku(vector<vector<char>>& board) {// 创建三个数组来记录每一行、每一列和每个子宫格中数字出现的次数int rows[9][9];   // rows[i][index] 代表第 i 行,数字 index+1 出现的次数int cols[9][9];   // cols[j][index] 代表第 j 列,数字 index+1 出现的次数int subboxs[3][3][9];  // subboxs[i/3][j/3][index] 代表第 (i/3, j/3) 子宫格中数字 index+1 出现的次数// 初始化三个数组,将所有计数值设为 0memset(rows,0,sizeof(rows));  // 将所有行的数字计数清零memset(cols,0,sizeof(cols));  // 将所有列的数字计数清零memset(subboxs,0,sizeof(subboxs));  // 将所有子宫格的数字计数清零// 遍历数独棋盘的每个格子for (int i = 0; i < 9; i++) {  for (int j = 0; j < 9; j++) { char c = board[i][j];  // 获取当前格子的值if (c != '.') {  // 如果当前格子是一个数字(即不为空)int index = c - '1';  // 将字符转换为数字,'1' 对应 index 0,'9' 对应 index 8// 更新行、列和子宫格中该数字的计数rows[i][index]++;  // 更新第 i 行中该数字出现的次数cols[j][index]++;  // 更新第 j 列中该数字出现的次数subboxs[i / 3][j / 3][index]++;  // 更新第 (i/3, j/3) 子宫格中该数字出现的次数// 如果该数字在行、列或子宫格中出现超过一次,返回 falseif (rows[i][index] > 1 || cols[j][index] > 1 || subboxs[i / 3][j / 3][index] > 1) {return false;  // 数字重复,数独无效}}}}// 如果没有发现重复数字,返回 true,表示数独有效return true;  }
};
以思路二为例进行调试
#include<iostream>
#include<vector>
#include<unordered_set>
#include<cstring>
using namespace std;class Solution2 {
public:bool isValidSudoku(vector<vector<char>>& board) {// 创建三个数组来记录每一行、每一列和每个子宫格中数字出现的次数int rows[9][9];   // rows[i][index] 代表第 i 行,数字 index+1 出现的次数int cols[9][9];   // cols[j][index] 代表第 j 列,数字 index+1 出现的次数int subboxs[3][3][9];  // subboxs[i/3][j/3][index] 代表第 (i/3, j/3) 子宫格中数字 index+1 出现的次数// 初始化三个数组,将所有计数值设为 0memset(rows,0,sizeof(rows));  // 将所有行的数字计数清零memset(cols,0,sizeof(cols));  // 将所有列的数字计数清零memset(subboxs,0,sizeof(subboxs));  // 将所有子宫格的数字计数清零// 遍历数独棋盘的每个格子for (int i = 0; i < 9; i++) {  for (int j = 0; j < 9; j++) { char c = board[i][j];  // 获取当前格子的值if (c != '.') {  // 如果当前格子是一个数字(即不为空)int index = c - '1';  // 将字符转换为数字,'1' 对应 index 0,'9' 对应 index 8// 更新行、列和子宫格中该数字的计数rows[i][index]++;  // 更新第 i 行中该数字出现的次数cols[j][index]++;  // 更新第 j 列中该数字出现的次数subboxs[i / 3][j / 3][index]++;  // 更新第 (i/3, j/3) 子宫格中该数字出现的次数// 如果该数字在行、列或子宫格中出现超过一次,返回 falseif (rows[i][index] > 1 || cols[j][index] > 1 || subboxs[i / 3][j / 3][index] > 1) {return false;  // 数字重复,数独无效}}}}// 如果没有发现重复数字,返回 true,表示数独有效return true;  }
};int main(int argc, char const *argv[])
{vector<vector<char>> 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'}}};Solution2 s;if (s.isValidSudoku(board)){cout<<"true"<<endl;}else{cout<<"false"<<endl;}return 0;
}

LeetCode 面试经典 150_矩阵_有效的数独(34_36)原题链接
欢迎大家和我沟通交流(✿◠‿◠)


文章转载自:

http://Qv05dtzG.xsqyn.cn
http://SAnPJXb6.xsqyn.cn
http://jjljDqTO.xsqyn.cn
http://wMQgCZF2.xsqyn.cn
http://YCBTcfMm.xsqyn.cn
http://qVwwEOaK.xsqyn.cn
http://rGoYqd9R.xsqyn.cn
http://YfUkeTxJ.xsqyn.cn
http://F5oSuGKM.xsqyn.cn
http://OUvz8shX.xsqyn.cn
http://VbigGLKS.xsqyn.cn
http://IGf4RcZX.xsqyn.cn
http://cyE7OMmD.xsqyn.cn
http://t6rguHq2.xsqyn.cn
http://iIgsSxl5.xsqyn.cn
http://ZEfXoCVV.xsqyn.cn
http://fgSWBIm6.xsqyn.cn
http://SSaGakUg.xsqyn.cn
http://kgSbPgyR.xsqyn.cn
http://RcuuWvx4.xsqyn.cn
http://3VszjcNv.xsqyn.cn
http://MUyYxHUy.xsqyn.cn
http://dPAoUJpy.xsqyn.cn
http://QznNrq8v.xsqyn.cn
http://atXTa1ZD.xsqyn.cn
http://CfMHUfNx.xsqyn.cn
http://KtxXhCUZ.xsqyn.cn
http://LSJrhqL5.xsqyn.cn
http://YopHTUQ9.xsqyn.cn
http://UuPuU47d.xsqyn.cn
http://www.dtcms.com/a/364697.html

相关文章:

  • 腾讯开源HunyuanWorld-Voyager突破性原生3D重建与视频扩散框架
  • Go 语言面试题详解之接口 (Interface) 详解一文吃透
  • 汽车工装结构件3D扫描尺寸测量公差比对-中科米堆CASAIM
  • 为什么几行dropout就能显著提升稀疏3DGS渲染质量?
  • 网格图--Day04--网格图DFS--2684. 矩阵中移动的最大次数,1254. 统计封闭岛屿的数目,130. 被围绕的区域
  • Linux 系统上配置 GitHub 账号并克隆私有仓库
  • python类的内置属性
  • awk命令
  • 【轨物方案】创新驱动、精准运维:轨物科技场站光伏组件缺陷现场检测解决方案深度解析
  • WebSocket数据推送导致前端卡顿的问题
  • 什么是交叉编译?
  • Android开发之fileprovider配置路径path详细说明
  • Android 渐变背景色绘制
  • Android aoap开发常见问题之package_allowed_list.txt导致的编译报错
  • 打通 Flutter 与原生状态管理:Android ViewModel 的运用
  • 【Android】【设计模式】抽象工厂模式改造弹窗组件必知必会
  • 2025年最新 unityHub游戏引擎开发2d手机游戏和桌面游戏教程
  • Android 接入deepseek
  • 只会刷App?大学生学透Android开发,直接开挂!
  • HTTP协议——理解相关概念、模拟实现浏览器访问自定义服务器
  • PixPin截图工具完全体下载|解决Snipaste无法长截图问题+比QQ截图更专业+无广告绿色版支持Win7-Win11全系统兼容
  • Java:跨越时代的编程语言,持续赋能数字化转型
  • Ansible高效管理大项目实战技巧
  • 【GitOps】初始Argo CD
  • 《用 Flask 构建 RESTful API:用户数据管理的实战指南》
  • Spring Boot 2.7 中资源销毁的先后顺序
  • 从源码入手,详解Linux进程
  • Ollama大模型 本地部署+使用教程
  • 《WINDOWS 环境下32位汇编语言程序设计》第11章 动态链接库和钩子
  • 9月3日