leetcode 面试经典 150 题:有效的数独

devtools/2024/12/28 10:50:59/
链接有效的数独
题序号36
题型数组
解题方法双层for循环一次遍历法
难度中等
熟练度✅✅✅

题目

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

数字 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”]]
    输出: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)或者 ‘.’

题解

  1. 核心要点
    • 检查每一行:对于数独的每一行,我们需要确保数字1-9只出现一次。我们可以使用一个长度为9的数组(或者集合)来记录每一行中已经出现过的数字。

    • 检查每一列:类似地,对于每一列,我们也需要确保数字1-9只出现一次。同样使用一个长度为9的数组(或者集合)来记录每一列中已经出现过的数字。

    • 检查每一个3x3宫格:在数独中,有9个3x3的宫格,我们需要确保在每一个宫格内,数字1-9只出现一次。我们可以使用9个长度为9的数组(或者集合)来记录每个宫格中已经出现过的数字。

    • 遍历数独板:从左到右,从上到下,遍历数独板上的每一个单元格。对于非空单元格(即不是’.'的单元格),检查其值是否已经在当前行、列或宫格中出现过。如果出现过,则数独无效;否则,将该值添加到当前行、列和宫格的记录中。

    • 返回结果:如果遍历完所有单元格后没有发现任何重复,则数独有效;否则,数独无效。

  2. 时间复杂度:O(1)。数独共有 81 个单元格,只需要对每个单元格遍历一次即可。
  3. 空间复杂度:O(1)。由于数独的大小固定,因此哈希表的空间也是固定的。
  4. c++ 实现算法
bool isValidSudoku(vector<vector<char>>& board) {vector<unordered_set<char>> rows(9); // 存储每一行的数字vector<unordered_set<char>> cols(9); // 存储每一列的数字vector<unordered_set<char>> boxes(9); // 存储每个 3x3 子区域的数字for (int i = 0; i < 9; ++i) {for (int j = 0; j < 9; ++j) {char num = board[i][j];if (num == '.') continue; //如果当前格子是 '.'(空格),直接跳过。int boxIndex = (i / 3) * 3 + j / 3; // 计算子区域索引,通过该公式计算当前格子属于哪个子区域。// 检查行、列和子区域中是否已经存在该数字if (rows[i].count(num) || cols[j].count(num) || boxes[boxIndex].count(num)) {return false;}// 将数字添加到对应的集合中//rows[i]: 记录数字在第 i 行中出现。// cols[j]: 记录数字在第 j 列中出现。//boxes[boxIndex]: 记录数字在当前子区域中出现。rows[i].insert(num);cols[j].insert(num);boxes[boxIndex].insert(num);}}return true;
}
  1. 演示:以示例1为例
/*遍历每个格子
按照 for (i, j) 遍历 9×9 的棋盘。第一步:board[0][0]
当前格子:'5',属于 第 0 行,第 0 列,左上角子区域。
检查:
rows[0]:空集合,数字 '5' 不存在。
cols[0]:空集合,数字 '5' 不存在。
boxes[0]:空集合,数字 '5' 不存在。
动作:将 '5' 插入:
rows[0]{ '5' }
cols[0]{ '5' }
boxes[0]{ '5' }第二步:board[0][1]
当前格子:'3',属于 第 0 行,第 1 列,左上角子区域。
检查:
rows[0]{ '5' },数字 '3' 不存在。
cols[1]:空集合,数字 '3' 不存在。
boxes[0]{ '5' },数字 '3' 不存在。
动作:将 '3' 插入:
rows[0]{ '5', '3' }
cols[1]{ '3' }
boxes[0]{ '5', '3' }第三步:board[0][2]
当前格子:'.',跳过。第四步:board[0][4]
当前格子:'7',属于 第 0 行,第 4 列,中间子区域。
检查:
rows[0]{ '5', '3' },数字 '7' 不存在。
cols[4]:空集合,数字 '7' 不存在。
boxes[1]:空集合,数字 '7' 不存在。
动作:将 '7' 插入:
rows[0]{ '5', '3', '7' }
cols[4]{ '7' }
boxes[1]{ '7' }第五步:board[1][0]
当前格子:'6',属于 第 1 行,第 0 列,左上角子区域。
检查:
rows[1]:空集合,数字 '6' 不存在。
cols[0]{ '5' },数字 '6' 不存在。
boxes[0]{ '5', '3' },数字 '6' 不存在。
动作:将 '6' 插入:
rows[1]{ '6' }
cols[0]{ '5', '6' }
boxes[0]{ '5', '3', '6' }其余步骤
程序继续按顺序遍历,重复检查和插入:遇到 '.' 跳过。
若数字未重复,插入到对应的 rows[i]、cols[j] 和 boxes[boxIndex]。*/
  1. 完整c++ demo
#include <vector>
#include <unordered_set>
#include <iostream>
using namespace std;bool isValidSudoku(vector<vector<char>>& board) {vector<unordered_set<char>> rows(9); // 存储每一行的数字vector<unordered_set<char>> cols(9); // 存储每一列的数字vector<unordered_set<char>> boxes(9); // 存储每个 3x3 子区域的数字for (int i = 0; i < 9; ++i) {for (int j = 0; j < 9; ++j) {char num = board[i][j];if (num == '.') continue; //如果当前格子是 '.'(空格),直接跳过。int boxIndex = (i / 3) * 3 + j / 3; // 计算子区域索引,通过该公式计算当前格子属于哪个子区域。// 检查行、列和子区域中是否已经存在该数字if (rows[i].count(num) || cols[j].count(num) || boxes[boxIndex].count(num)) {return false;}// 将数字添加到对应的集合中//rows[i]: 记录数字在第 i 行中出现。// cols[j]: 记录数字在第 j 列中出现。//boxes[boxIndex]: 记录数字在当前子区域中出现。rows[i].insert(num);cols[j].insert(num);boxes[boxIndex].insert(num);}}return true;
}int main() {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'}};cout << (isValidSudoku(board) ? "True" : "False") << endl;return 0;
}

http://www.ppmy.cn/devtools/146091.html

相关文章

一个从oracle使用spool导出数据到kadb的脚本

1. dump_data.sh调用sql_dump.sh导出数据 2. load_data.sh将导出的数据加载至KADB 1. dump_data.sh #!/bin/bash begin_time$(date %Y%m%d -d -1 day) end_time$(date %Y%m%d) echo "数据导出日期:"$begin_time echo "数据导出日期:"$begin_time >>…

《机器学习》KNN算法实现手写数字识别

目录 一、项目介绍 二、数据集介绍 三、需要解决的问题 四、代码实际展示 代码展示 实验结果 五、使用自己的数据进行测试 代码展示 结果展示 六、总结 一、项目介绍 通过对一张2000*1000像素写满0-9手写数字的图片进行处理。分割出训练集和测试集使用KNN算法进行训练…

STM32使用UART发送字符串与printf输出重定向

首先我们先看STM32F103C8T6的电路图 由图可知&#xff0c;其PA9和PA10引脚分别为UART的TX和RX(注意&#xff1a;这个电路图是错误的&#xff0c;应该是PA9是X而PA9是RX&#xff0c;我们看下图的官方文件可以看出)&#xff0c;那么接下来我们应该找到该引脚的定义是什么&#xf…

[银河麒麟] Geogebra

Geogebra 几何作图工具 是一款跨平台的几何作图工具软件&#xff0c; 目前已经覆盖了&#xff0c; windows&#xff0c;android&#xff0c; mac, linux 等操作系统。 Geogebra 官网 Geogebra 官网提供了 Geogebra 5.0 版本下载包, Linux Portable 双击 geogebra-portable…

基于自然语言处理(NLP)的智能客服系统

基于自然语言处理&#xff08;NLP&#xff09;的智能客服系统是现代客户服务领域的一项重要技术&#xff0c;它通过模拟人类对话的方式&#xff0c;为用户提供及时、准确和个性化的服务。以下是关于基于NLP的智能客服系统的一些关键要素和功能&#xff1a; 1. 自然语言理解&am…

无人机+自组网+通信指挥车:应急救援空地技术详解

“无人机自组网通信指挥车”这一组合在应急救援领域展现出了强大的空地协同能力&#xff0c;为救援行动提供了高效、实时的信息支持和指挥决策。以下是对这一应急救援空地技术的详细解析&#xff1a; 一、系统组成 1. 无人机 作为空中平台&#xff0c;无人机具备广阔的视野和…

通过Cephadm工具搭建Ceph分布式存储以及通过文件系统形式进行挂载的步骤

1、什么是Ceph Ceph是一种开源、分布式存储系统&#xff0c;旨在提供卓越的性能、可靠性和可伸缩性。它是为了解决大规模数据存储问题而设计的&#xff0c;使得用户可以在无需特定硬件支持的前提下&#xff0c;通过普通的硬件设备来部署和管理存储解决方案。Ceph的灵活性和设计…

Android 之 Activity 的启动模式(launchMode)

一、Activity 启动模式 在实际项目中&#xff0c;应该根据项目的实际需要来为每个 Activity 指定恰当的启动模式 launchMode。启动模式一共有四种&#xff0c;分别是 standard、singleTop、singleTask 和 singleInstance。可以在 AndroidManifest.xml 中通过给 <activity&g…